aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/X11/Xrm.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/lib/X11/Xrm.c')
-rw-r--r--nx-X11/lib/X11/Xrm.c2651
1 files changed, 0 insertions, 2651 deletions
diff --git a/nx-X11/lib/X11/Xrm.c b/nx-X11/lib/X11/Xrm.c
deleted file mode 100644
index e3587d021..000000000
--- a/nx-X11/lib/X11/Xrm.c
+++ /dev/null
@@ -1,2651 +0,0 @@
-
-/***********************************************************
-Copyright 1987, 1988, 1990 by Digital Equipment Corporation, Maynard
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-/*
-
-Copyright 1987, 1988, 1990, 1998 The Open Group
-
-Permission to use, copy, modify, distribute, and sell this software and its
-documentation for any purpose is hereby granted without fee, provided that
-the above copyright notice appear in all copies and that both that
-copyright notice and this permission notice appear in supporting
-documentation.
-
-The above copyright notice and this permission notice shall be included
-in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
-ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall
-not be used in advertising or otherwise to promote the sale, use or
-other dealings in this Software without prior written authorization
-from The Open Group.
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <ctype.h>
-#include "Xlibint.h"
-#include <nx-X11/Xresource.h>
-#include "Xlcint.h"
-#ifdef XTHREADS
-#include "locking.h"
-#endif
-#include <nx-X11/Xos.h>
-#include <sys/stat.h>
-#include <limits.h>
-#include "Xresinternal.h"
-#include "Xresource.h"
-
-/*
-
-These Xrm routines allow very fast lookup of resources in the resource
-database. Several usage patterns are exploited:
-
-(1) Widgets get a lot of resources at one time. Rather than look up each from
-scratch, we can precompute the prioritized list of database levels once, then
-search for each resource starting at the beginning of the list.
-
-(2) Many database levels don't contain any leaf resource nodes. There is no
-point in looking for resources on a level that doesn't contain any. This
-information is kept on a per-level basis.
-
-(3) Sometimes the widget instance tree is structured such that you get the same
-class name repeated on the fully qualified widget name. This can result in the
-same database level occuring multiple times on the search list. The code below
-only checks to see if you get two identical search lists in a row, rather than
-look back through all database levels, but in practice this removes all
-duplicates I've ever observed.
-
-Joel McCormack
-
-*/
-
-/*
-
-The Xrm representation has been completely redesigned to substantially reduce
-memory and hopefully improve performance.
-
-The database is structured into two kinds of tables: LTables that contain
-only values, and NTables that contain only other tables.
-
-Some invariants:
-
-The next pointer of the top-level node table points to the top-level leaf
-table, if any.
-
-Within an LTable, for a given name, the tight value always precedes the
-loose value, and if both are present the loose value is always right after
-the tight value.
-
-Within an NTable, all of the entries for a given name are contiguous,
-in the order tight NTable, loose NTable, tight LTable, loose LTable.
-
-Bob Scheifler
-
-*/
-
-static XrmQuark XrmQString, XrmQANY;
-
-typedef Bool (*DBEnumProc)(
- XrmDatabase* /* db */,
- XrmBindingList /* bindings */,
- XrmQuarkList /* quarks */,
- XrmRepresentation* /* type */,
- XrmValue* /* value */,
- XPointer /* closure */
-);
-
-typedef struct _VEntry {
- struct _VEntry *next; /* next in chain */
- XrmQuark name; /* name of this entry */
- unsigned int tight:1; /* 1 if it is a tight binding */
- unsigned int string:1; /* 1 if type is String */
- unsigned int size:30; /* size of value */
-} VEntryRec, *VEntry;
-
-
-typedef struct _DEntry {
- VEntryRec entry; /* entry */
- XrmRepresentation type; /* representation type */
-} DEntryRec, *DEntry;
-
-/* the value is right after the structure */
-#define StringValue(ve) (XPointer)((ve) + 1)
-#define RepType(ve) ((DEntry)(ve))->type
-/* the value is right after the structure */
-#define DataValue(ve) (XPointer)(((DEntry)(ve)) + 1)
-#define RawValue(ve) (char *)((ve)->string ? StringValue(ve) : DataValue(ve))
-
-typedef struct _NTable {
- struct _NTable *next; /* next in chain */
- XrmQuark name; /* name of this entry */
- unsigned int tight:1; /* 1 if it is a tight binding */
- unsigned int leaf:1; /* 1 if children are values */
- unsigned int hasloose:1; /* 1 if has loose children */
- unsigned int hasany:1; /* 1 if has ANY entry */
- unsigned int pad:4; /* unused */
- unsigned int mask:8; /* hash size - 1 */
- unsigned int entries:16; /* number of children */
-} NTableRec, *NTable;
-
-/* the buckets are right after the structure */
-#define NodeBuckets(ne) ((NTable *)((ne) + 1))
-#define NodeHash(ne,q) NodeBuckets(ne)[(q) & (ne)->mask]
-
-/* leaf tables have an extra level of indirection for the buckets,
- * so that resizing can be done without invalidating a search list.
- * This is completely ugly, and wastes some memory, but the Xlib
- * spec doesn't really specify whether invalidation is OK, and the
- * old implementation did not invalidate.
- */
-typedef struct _LTable {
- NTableRec table;
- VEntry *buckets;
-} LTableRec, *LTable;
-
-#define LeafHash(le,q) (le)->buckets[(q) & (le)->table.mask]
-
-/* An XrmDatabase just holds a pointer to the first top-level table.
- * The type name is no longer descriptive, but better to not change
- * the Xresource.h header file. This type also gets used to define
- * XrmSearchList, which is a complete crock, but we'll just leave it
- * and caste types as required.
- */
-typedef struct _XrmHashBucketRec {
- NTable table;
- XPointer mbstate;
- XrmMethods methods;
-#ifdef XTHREADS
- LockInfoRec linfo;
-#endif
-} XrmHashBucketRec;
-
-/* closure used in get/put resource */
-typedef struct _VClosure {
- XrmRepresentation *type; /* type of value */
- XrmValuePtr value; /* value itself */
-} VClosureRec, *VClosure;
-
-/* closure used in get search list */
-typedef struct _SClosure {
- LTable *list; /* search list */
- int idx; /* index of last filled element */
- int limit; /* maximum index */
-} SClosureRec, *SClosure;
-
-/* placed in XrmSearchList to indicate next table is loose only */
-#define LOOSESEARCH ((LTable)1)
-
-/* closure used in enumerate database */
-typedef struct _EClosure {
- XrmDatabase db; /* the database */
- DBEnumProc proc; /* the user proc */
- XPointer closure; /* the user closure */
- XrmBindingList bindings; /* binding list */
- XrmQuarkList quarks; /* quark list */
- int mode; /* XrmEnum<kind> */
-} EClosureRec, *EClosure;
-
-/* types for typecasting ETable based functions to NTable based functions */
-typedef Bool (*getNTableSProcp)(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- SClosure closure);
-typedef Bool (*getNTableVProcp)(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- VClosure closure);
-typedef Bool (*getNTableEProcp)(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- register int level,
- EClosure closure);
-
-/* predicate to determine when to resize a hash table */
-#define GrowthPred(n,m) ((unsigned)(n) > (((m) + 1) << 2))
-
-#define GROW(prev) \
- if (GrowthPred((*prev)->entries, (*prev)->mask)) \
- GrowTable(prev)
-
-/* pick a reasonable value for maximum depth of resource database */
-#define MAXDBDEPTH 100
-
-/* macro used in get/search functions */
-
-/* find an entry named ename, with leafness given by leaf */
-#define NFIND(ename) \
- q = ename; \
- entry = NodeHash(table, q); \
- while (entry && entry->name != q) \
- entry = entry->next; \
- if (leaf && entry && !entry->leaf) { \
- entry = entry->next; \
- if (entry && !entry->leaf) \
- entry = entry->next; \
- if (entry && entry->name != q) \
- entry = (NTable)NULL; \
- }
-
-/* resourceQuarks keeps track of what quarks have been associated with values
- * in all LTables. If a quark has never been used in an LTable, we don't need
- * to bother looking for it.
- */
-
-static unsigned char *resourceQuarks = (unsigned char *)NULL;
-static XrmQuark maxResourceQuark = -1;
-
-/* determines if a quark has been used for a value in any database */
-#define IsResourceQuark(q) ((q) > 0 && (q) <= maxResourceQuark && \
- resourceQuarks[(q) >> 3] & (1 << ((q) & 7)))
-
-typedef unsigned char XrmBits;
-
-#define BSLASH ((XrmBits) (1 << 5))
-#define NORMAL ((XrmBits) (1 << 4))
-#define EOQ ((XrmBits) (1 << 3))
-#define SEP ((XrmBits) (1 << 2))
-#define ENDOF ((XrmBits) (1 << 1))
-#define SPACE (NORMAL|EOQ|SEP|(XrmBits)0)
-#define RSEP (NORMAL|EOQ|SEP|(XrmBits)1)
-#define EOS (EOQ|SEP|ENDOF|(XrmBits)0)
-#define EOL (EOQ|SEP|ENDOF|(XrmBits)1)
-#define BINDING (NORMAL|EOQ)
-#define ODIGIT (NORMAL|(XrmBits)1)
-
-#define next_char(ch,str) xrmtypes[(unsigned char)((ch) = *(++(str)))]
-#define next_mbchar(ch,len,str) xrmtypes[(unsigned char)(ch = (*db->methods->mbchar)(db->mbstate, str, &len), str += len, ch)]
-
-#define is_space(bits) ((bits) == SPACE)
-#define is_EOQ(bits) ((bits) & EOQ)
-#define is_EOF(bits) ((bits) == EOS)
-#define is_EOL(bits) ((bits) & ENDOF)
-#define is_binding(bits) ((bits) == BINDING)
-#define is_odigit(bits) ((bits) == ODIGIT)
-#define is_separator(bits) ((bits) & SEP)
-#define is_nonpcs(bits) (!(bits))
-#define is_normal(bits) ((bits) & NORMAL)
-#define is_simple(bits) ((bits) & (NORMAL|BSLASH))
-#define is_special(bits) ((bits) & (ENDOF|BSLASH))
-
-/* parsing types */
-static XrmBits const xrmtypes[256] = {
- EOS,0,0,0,0,0,0,0,
- 0,SPACE,EOL,0,0,
-#if defined(WIN32)
- EOL, /* treat CR the same as LF, just in case */
-#else
- 0,
-#endif
- 0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- SPACE,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,BINDING,NORMAL,NORMAL,NORMAL,BINDING,NORMAL,
- ODIGIT,ODIGIT,ODIGIT,ODIGIT,ODIGIT,ODIGIT,ODIGIT,ODIGIT,
- NORMAL,NORMAL,RSEP,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,BSLASH,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,
- NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,NORMAL,0
- /* The rest will be automatically initialized to zero. */
-};
-
-void XrmInitialize(void)
-{
- XrmQString = XrmPermStringToQuark("String");
- XrmQANY = XrmPermStringToQuark("?");
-}
-
-XrmDatabase XrmGetDatabase(
- Display *display)
-{
- XrmDatabase retval;
- LockDisplay(display);
- retval = display->db;
- UnlockDisplay(display);
- return retval;
-}
-
-void XrmSetDatabase(
- Display *display,
- XrmDatabase database)
-{
- LockDisplay(display);
- /* destroy database if set up implicitly by XGetDefault() */
- if (display->db && (display->flags & XlibDisplayDfltRMDB)) {
- XrmDestroyDatabase(display->db);
- display->flags &= ~XlibDisplayDfltRMDB;
- }
- display->db = database;
- UnlockDisplay(display);
-}
-
-void
-XrmStringToQuarkList(
- register _Xconst char *name,
- register XrmQuarkList quarks) /* RETURN */
-{
- register XrmBits bits;
- register Signature sig = 0;
- register char ch, *tname;
- register int i = 0;
-
- if ((tname = (char *)name)) {
- tname--;
- while (!is_EOF(bits = next_char(ch, tname))) {
- if (is_binding (bits)) {
- if (i) {
- /* Found a complete name */
- *quarks++ = _XrmInternalStringToQuark(name,tname - name,
- sig, False);
- i = 0;
- sig = 0;
- }
- name = tname+1;
- }
- else {
- sig = (sig << 1) + ch; /* Compute the signature. */
- i++;
- }
- }
- *quarks++ = _XrmInternalStringToQuark(name, tname - name, sig, False);
- }
- *quarks = NULLQUARK;
-}
-
-void
-XrmStringToBindingQuarkList(
- register _Xconst char *name,
- register XrmBindingList bindings, /* RETURN */
- register XrmQuarkList quarks) /* RETURN */
-{
- register XrmBits bits;
- register Signature sig = 0;
- register char ch, *tname;
- register XrmBinding binding;
- register int i = 0;
-
- if ((tname = (char *)name)) {
- tname--;
- binding = XrmBindTightly;
- while (!is_EOF(bits = next_char(ch, tname))) {
- if (is_binding (bits)) {
- if (i) {
- /* Found a complete name */
- *bindings++ = binding;
- *quarks++ = _XrmInternalStringToQuark(name, tname - name,
- sig, False);
-
- i = 0;
- sig = 0;
- binding = XrmBindTightly;
- }
- name = tname+1;
-
- if (ch == '*')
- binding = XrmBindLoosely;
- }
- else {
- sig = (sig << 1) + ch; /* Compute the signature. */
- i++;
- }
- }
- *bindings = binding;
- *quarks++ = _XrmInternalStringToQuark(name, tname - name, sig, False);
- }
- *quarks = NULLQUARK;
-}
-
-#ifdef DEBUG
-
-static void PrintQuarkList(
- XrmQuarkList quarks,
- FILE *stream)
-{
- Bool firstNameSeen;
-
- for (firstNameSeen = False; *quarks; quarks++) {
- if (firstNameSeen) {
- (void) fprintf(stream, ".");
- }
- firstNameSeen = True;
- (void) fputs(XrmQuarkToString(*quarks), stream);
- }
-} /* PrintQuarkList */
-
-#endif /* DEBUG */
-
-
-/*
- * Fallback methods for Xrm parsing.
- * Simulate a C locale. No state needed here.
- */
-
-static void
-c_mbnoop(
- XPointer state)
-{
-}
-
-static char
-c_mbchar(
- XPointer state,
- const char *str,
- int *lenp)
-{
- *lenp = 1;
- return *str;
-}
-
-static const char *
-c_lcname(
- XPointer state)
-{
- return "C";
-}
-
-static const XrmMethodsRec mb_methods = {
- c_mbnoop, /* mbinit */
- c_mbchar, /* mbchar */
- c_mbnoop, /* mbfinish */
- c_lcname, /* lcname */
- c_mbnoop /* destroy */
-};
-
-
-static XrmDatabase NewDatabase(void)
-{
- register XrmDatabase db;
-
- db = Xmalloc(sizeof(XrmHashBucketRec));
- if (db) {
- _XCreateMutex(&db->linfo);
- db->table = (NTable)NULL;
- db->mbstate = (XPointer)NULL;
- db->methods = _XrmInitParseInfo(&db->mbstate);
- if (!db->methods)
- db->methods = &mb_methods;
- }
- return db;
-}
-
-/* move all values from ftable to ttable, and free ftable's buckets.
- * ttable is guaranteed empty to start with.
- */
-static void MoveValues(
- LTable ftable,
- register LTable ttable)
-{
- register VEntry fentry, nfentry;
- register VEntry *prev;
- register VEntry *bucket;
- register VEntry tentry;
- register int i;
-
- for (i = ftable->table.mask, bucket = ftable->buckets; i >= 0; i--) {
- for (fentry = *bucket++; fentry; fentry = nfentry) {
- prev = &LeafHash(ttable, fentry->name);
- tentry = *prev;
- *prev = fentry;
- /* chain on all with same name, to preserve invariant order */
- while ((nfentry = fentry->next) && nfentry->name == fentry->name)
- fentry = nfentry;
- fentry->next = tentry;
- }
- }
- Xfree(ftable->buckets);
-}
-
-/* move all tables from ftable to ttable, and free ftable.
- * ttable is quaranteed empty to start with.
- */
-static void MoveTables(
- NTable ftable,
- register NTable ttable)
-{
- register NTable fentry, nfentry;
- register NTable *prev;
- register NTable *bucket;
- register NTable tentry;
- register int i;
-
- for (i = ftable->mask, bucket = NodeBuckets(ftable); i >= 0; i--) {
- for (fentry = *bucket++; fentry; fentry = nfentry) {
- prev = &NodeHash(ttable, fentry->name);
- tentry = *prev;
- *prev = fentry;
- /* chain on all with same name, to preserve invariant order */
- while ((nfentry = fentry->next) && nfentry->name == fentry->name)
- fentry = nfentry;
- fentry->next = tentry;
- }
- }
- Xfree(ftable);
-}
-
-/* grow the table, based on current number of entries */
-static void GrowTable(
- NTable *prev)
-{
- register NTable table;
- register int i;
-
- table = *prev;
- i = table->mask;
- if (i == 255) /* biggest it gets */
- return;
- while (i < 255 && GrowthPred(table->entries, i))
- i = (i << 1) + 1;
- i++; /* i is now the new size */
- if (table->leaf) {
- register LTable ltable;
- LTableRec otable;
-
- ltable = (LTable)table;
- /* cons up a copy to make MoveValues look symmetric */
- otable = *ltable;
- ltable->buckets = Xcalloc(i, sizeof(VEntry));
- if (!ltable->buckets) {
- ltable->buckets = otable.buckets;
- return;
- }
- ltable->table.mask = i - 1;
- MoveValues(&otable, ltable);
- } else {
- register NTable ntable;
-
- ntable = Xcalloc(1, sizeof(NTableRec) + (i * sizeof(NTable)));
- if (!ntable)
- return;
- *ntable = *table;
- ntable->mask = i - 1;
- *prev = ntable;
- MoveTables(table, ntable);
- }
-}
-
-/* merge values from ftable into *pprev, destroy ftable in the process */
-static void MergeValues(
- LTable ftable,
- NTable *pprev,
- Bool override)
-{
- register VEntry fentry, tentry;
- register VEntry *prev;
- register LTable ttable;
- VEntry *bucket;
- int i;
- register XrmQuark q;
-
- ttable = (LTable)*pprev;
- if (ftable->table.hasloose)
- ttable->table.hasloose = 1;
- for (i = ftable->table.mask, bucket = ftable->buckets;
- i >= 0;
- i--, bucket++) {
- for (fentry = *bucket; fentry; ) {
- q = fentry->name;
- prev = &LeafHash(ttable, q);
- tentry = *prev;
- while (tentry && tentry->name != q)
- tentry = *(prev = &tentry->next);
- /* note: test intentionally uses fentry->name instead of q */
- /* permits serendipitous inserts */
- while (tentry && tentry->name == fentry->name) {
- /* if tentry is earlier, skip it */
- if (!fentry->tight && tentry->tight) {
- tentry = *(prev = &tentry->next);
- continue;
- }
- if (fentry->tight != tentry->tight) {
- /* no match, chain in fentry */
- *prev = fentry;
- prev = &fentry->next;
- fentry = *prev;
- *prev = tentry;
- ttable->table.entries++;
- } else if (override) {
- /* match, chain in fentry, splice out and free tentry */
- *prev = fentry;
- prev = &fentry->next;
- fentry = *prev;
- *prev = tentry->next;
- /* free the overridden entry */
- Xfree(tentry);
- /* get next tentry */
- tentry = *prev;
- } else {
- /* match, discard fentry */
- prev = &tentry->next;
- tentry = fentry; /* use as a temp var */
- fentry = fentry->next;
- /* free the overpowered entry */
- Xfree(tentry);
- /* get next tentry */
- tentry = *prev;
- }
- if (!fentry)
- break;
- }
- /* at this point, tentry cannot match any fentry named q */
- /* chain in all bindings together, preserve invariant order */
- while (fentry && fentry->name == q) {
- *prev = fentry;
- prev = &fentry->next;
- fentry = *prev;
- *prev = tentry;
- ttable->table.entries++;
- }
- }
- }
- Xfree(ftable->buckets);
- Xfree(ftable);
- /* resize if necessary, now that we're all done */
- GROW(pprev);
-}
-
-/* merge tables from ftable into *pprev, destroy ftable in the process */
-static void MergeTables(
- NTable ftable,
- NTable *pprev,
- Bool override)
-{
- register NTable fentry, tentry;
- NTable nfentry;
- register NTable *prev;
- register NTable ttable;
- NTable *bucket;
- int i;
- register XrmQuark q;
-
- ttable = *pprev;
- if (ftable->hasloose)
- ttable->hasloose = 1;
- if (ftable->hasany)
- ttable->hasany = 1;
- for (i = ftable->mask, bucket = NodeBuckets(ftable);
- i >= 0;
- i--, bucket++) {
- for (fentry = *bucket; fentry; ) {
- q = fentry->name;
- prev = &NodeHash(ttable, q);
- tentry = *prev;
- while (tentry && tentry->name != q)
- tentry = *(prev = &tentry->next);
- /* note: test intentionally uses fentry->name instead of q */
- /* permits serendipitous inserts */
- while (tentry && tentry->name == fentry->name) {
- /* if tentry is earlier, skip it */
- if ((fentry->leaf && !tentry->leaf) ||
- (!fentry->tight && tentry->tight &&
- (fentry->leaf || !tentry->leaf))) {
- tentry = *(prev = &tentry->next);
- continue;
- }
- nfentry = fentry->next;
- if (fentry->leaf != tentry->leaf ||
- fentry->tight != tentry->tight) {
- /* no match, just chain in */
- *prev = fentry;
- *(prev = &fentry->next) = tentry;
- ttable->entries++;
- } else {
- if (fentry->leaf)
- MergeValues((LTable)fentry, prev, override);
- else
- MergeTables(fentry, prev, override);
- /* bump to next tentry */
- tentry = *(prev = &(*prev)->next);
- }
- /* bump to next fentry */
- fentry = nfentry;
- if (!fentry)
- break;
- }
- /* at this point, tentry cannot match any fentry named q */
- /* chain in all bindings together, preserve invariant order */
- while (fentry && fentry->name == q) {
- *prev = fentry;
- prev = &fentry->next;
- fentry = *prev;
- *prev = tentry;
- ttable->entries++;
- }
- }
- }
- Xfree(ftable);
- /* resize if necessary, now that we're all done */
- GROW(pprev);
-}
-
-void XrmCombineDatabase(
- XrmDatabase from, XrmDatabase *into,
- Bool override)
-{
- register NTable *prev;
- register NTable ftable, ttable, nftable;
-
- if (!*into) {
- *into = from;
- } else if (from) {
- _XLockMutex(&from->linfo);
- _XLockMutex(&(*into)->linfo);
- if ((ftable = from->table)) {
- prev = &(*into)->table;
- ttable = *prev;
- if (!ftable->leaf) {
- nftable = ftable->next;
- if (ttable && !ttable->leaf) {
- /* both have node tables, merge them */
- MergeTables(ftable, prev, override);
- /* bump to into's leaf table, if any */
- ttable = *(prev = &(*prev)->next);
- } else {
- /* into has no node table, link from's in */
- *prev = ftable;
- *(prev = &ftable->next) = ttable;
- }
- /* bump to from's leaf table, if any */
- ftable = nftable;
- } else {
- /* bump to into's leaf table, if any */
- if (ttable && !ttable->leaf)
- ttable = *(prev = &ttable->next);
- }
- if (ftable) {
- /* if into has a leaf, merge, else insert */
- if (ttable)
- MergeValues((LTable)ftable, prev, override);
- else
- *prev = ftable;
- }
- }
- (from->methods->destroy)(from->mbstate);
- _XUnlockMutex(&from->linfo);
- _XFreeMutex(&from->linfo);
- Xfree(from);
- _XUnlockMutex(&(*into)->linfo);
- }
-}
-
-void XrmMergeDatabases(
- XrmDatabase from, XrmDatabase *into)
-{
- XrmCombineDatabase(from, into, True);
-}
-
-/* store a value in the database, overriding any existing entry */
-static void PutEntry(
- XrmDatabase db,
- XrmBindingList bindings,
- XrmQuarkList quarks,
- XrmRepresentation type,
- XrmValuePtr value)
-{
- register NTable *pprev, *prev;
- register NTable table;
- register XrmQuark q;
- register VEntry *vprev;
- register VEntry entry;
- NTable *nprev, *firstpprev;
-
-#define NEWTABLE(q,i) \
- table = Xmalloc(sizeof(LTableRec)); \
- if (!table) \
- return; \
- table->name = q; \
- table->hasloose = 0; \
- table->hasany = 0; \
- table->mask = 0; \
- table->entries = 0; \
- if (quarks[i]) { \
- table->leaf = 0; \
- nprev = NodeBuckets(table); \
- } else { \
- table->leaf = 1; \
- if (!(nprev = Xmalloc(sizeof(VEntry *)))) {\
- Xfree(table); \
- return; \
- } \
- ((LTable)table)->buckets = (VEntry *)nprev; \
- } \
- *nprev = (NTable)NULL; \
- table->next = *prev; \
- *prev = table
-
- if (!db || !*quarks)
- return;
- table = *(prev = &db->table);
- /* if already at leaf, bump to the leaf table */
- if (!quarks[1] && table && !table->leaf)
- table = *(prev = &table->next);
- pprev = prev;
- if (!table || (quarks[1] && table->leaf)) {
- /* no top-level node table, create one and chain it in */
- NEWTABLE(NULLQUARK,1);
- table->tight = 1; /* arbitrary */
- prev = nprev;
- } else {
- /* search along until we need a value */
- while (quarks[1]) {
- q = *quarks;
- table = *(prev = &NodeHash(table, q));
- while (table && table->name != q)
- table = *(prev = &table->next);
- if (!table)
- break; /* not found */
- if (quarks[2]) {
- if (table->leaf)
- break; /* not found */
- } else {
- if (!table->leaf) {
- /* bump to leaf table, if any */
- table = *(prev = &table->next);
- if (!table || table->name != q)
- break; /* not found */
- if (!table->leaf) {
- /* bump to leaf table, if any */
- table = *(prev = &table->next);
- if (!table || table->name != q)
- break; /* not found */
- }
- }
- }
- if (*bindings == XrmBindTightly) {
- if (!table->tight)
- break; /* not found */
- } else {
- if (table->tight) {
- /* bump to loose table, if any */
- table = *(prev = &table->next);
- if (!table || table->name != q ||
- !quarks[2] != table->leaf)
- break; /* not found */
- }
- }
- /* found that one, bump to next quark */
- pprev = prev;
- quarks++;
- bindings++;
- }
- if (!quarks[1]) {
- /* found all the way to a leaf */
- q = *quarks;
- entry = *(vprev = &LeafHash((LTable)table, q));
- while (entry && entry->name != q)
- entry = *(vprev = &entry->next);
- /* if want loose and have tight, bump to next entry */
- if (entry && *bindings == XrmBindLoosely && entry->tight)
- entry = *(vprev = &entry->next);
- if (entry && entry->name == q &&
- (*bindings == XrmBindTightly) == entry->tight) {
- /* match, need to override */
- if ((type == XrmQString) == entry->string &&
- entry->size == value->size) {
- /* update type if not String, can be different */
- if (!entry->string)
- RepType(entry) = type;
- /* identical size, just overwrite value */
- memcpy(RawValue(entry), (char *)value->addr, value->size);
- return;
- }
- /* splice out and free old entry */
- *vprev = entry->next;
- Xfree(entry);
- (*pprev)->entries--;
- }
- /* this is where to insert */
- prev = (NTable *)vprev;
- }
- }
- /* keep the top table, because we may have to grow it */
- firstpprev = pprev;
- /* iterate until we get to the leaf */
- while (quarks[1]) {
- /* build a new table and chain it in */
- NEWTABLE(*quarks,2);
- if (*quarks++ == XrmQANY)
- (*pprev)->hasany = 1;
- if (*bindings++ == XrmBindTightly) {
- table->tight = 1;
- } else {
- table->tight = 0;
- (*pprev)->hasloose = 1;
- }
- (*pprev)->entries++;
- pprev = prev;
- prev = nprev;
- }
- /* now allocate the value entry */
- entry = Xmalloc(((type == XrmQString) ?
- sizeof(VEntryRec) : sizeof(DEntryRec)) + value->size);
- if (!entry)
- return;
- entry->name = q = *quarks;
- if (*bindings == XrmBindTightly) {
- entry->tight = 1;
- } else {
- entry->tight = 0;
- (*pprev)->hasloose = 1;
- }
- /* chain it in, with a bit of type cast ugliness */
- entry->next = *((VEntry *)prev);
- *((VEntry *)prev) = entry;
- entry->size = value->size;
- if (type == XrmQString) {
- entry->string = 1;
- } else {
- entry->string = 0;
- RepType(entry) = type;
- }
- /* save a copy of the value */
- memcpy(RawValue(entry), (char *)value->addr, value->size);
- (*pprev)->entries++;
- /* this is a new leaf, need to remember it for search lists */
- if (q > maxResourceQuark) {
- unsigned oldsize = (maxResourceQuark + 1) >> 3;
- unsigned size = ((q | 0x7f) + 1) >> 3; /* reallocate in chunks */
- if (resourceQuarks) {
- unsigned char *prevQuarks = resourceQuarks;
-
- resourceQuarks = Xrealloc(resourceQuarks, size);
- if (!resourceQuarks) {
- Xfree(prevQuarks);
- }
- } else
- resourceQuarks = Xmalloc(size);
- if (resourceQuarks) {
- bzero((char *)&resourceQuarks[oldsize], size - oldsize);
- maxResourceQuark = (size << 3) - 1;
- } else {
- maxResourceQuark = -1;
- }
- }
- if (q > 0 && resourceQuarks)
- resourceQuarks[q >> 3] |= 1 << (q & 0x7);
- GROW(firstpprev);
-
-#undef NEWTABLE
-}
-
-void XrmQPutResource(
- XrmDatabase *pdb,
- XrmBindingList bindings,
- XrmQuarkList quarks,
- XrmRepresentation type,
- XrmValuePtr value)
-{
- if (!*pdb) *pdb = NewDatabase();
- _XLockMutex(&(*pdb)->linfo);
- PutEntry(*pdb, bindings, quarks, type, value);
- _XUnlockMutex(&(*pdb)->linfo);
-}
-
-void
-XrmPutResource(
- XrmDatabase *pdb,
- _Xconst char *specifier,
- _Xconst char *type,
- XrmValuePtr value)
-{
- XrmBinding bindings[MAXDBDEPTH+1];
- XrmQuark quarks[MAXDBDEPTH+1];
-
- if (!*pdb) *pdb = NewDatabase();
- _XLockMutex(&(*pdb)->linfo);
- XrmStringToBindingQuarkList(specifier, bindings, quarks);
- PutEntry(*pdb, bindings, quarks, XrmStringToQuark(type), value);
- _XUnlockMutex(&(*pdb)->linfo);
-}
-
-void
-XrmQPutStringResource(
- XrmDatabase *pdb,
- XrmBindingList bindings,
- XrmQuarkList quarks,
- _Xconst char *str)
-{
- XrmValue value;
-
- if (!*pdb) *pdb = NewDatabase();
- value.addr = (XPointer) str;
- value.size = strlen(str)+1;
- _XLockMutex(&(*pdb)->linfo);
- PutEntry(*pdb, bindings, quarks, XrmQString, &value);
- _XUnlockMutex(&(*pdb)->linfo);
-}
-
-/* Function Name: GetDatabase
- * Description: Parses a string and stores it as a database.
- * Arguments: db - the database.
- * str - a pointer to the string containing the database.
- * filename - source filename, if any.
- * doall - whether to do all lines or just one
- */
-
-/*
- * This function is highly optimized to inline as much as possible.
- * Be very careful with modifications, or simplifications, as they
- * may adversely affect the performance.
- *
- * Chris Peterson, MIT X Consortium 5/17/90.
- */
-
-/*
- * Xlib spec says max 100 quarks in a lookup, will stop and return if
- * return if any single production's lhs has more than 100 components.
- */
-#define QLIST_SIZE 100
-
-/*
- * This should be big enough to handle things like the XKeysymDB or biggish
- * ~/.Xdefaults or app-defaults files. Anything bigger will be allocated on
- * the heap.
- */
-#define DEF_BUFF_SIZE 8192
-
-static void GetIncludeFile(
- XrmDatabase db,
- _Xconst char *base,
- _Xconst char *fname,
- int fnamelen,
- int depth);
-
-static void GetDatabase(
- XrmDatabase db,
- _Xconst char *str,
- _Xconst char *filename,
- Bool doall,
- int depth)
-{
- char *rhs;
- char *lhs, lhs_s[DEF_BUFF_SIZE];
- XrmQuark quarks[QLIST_SIZE + 1]; /* allow for a terminal NullQuark */
- XrmBinding bindings[QLIST_SIZE + 1];
-
- register char *ptr;
- register XrmBits bits = 0;
- register char c;
- register Signature sig;
- register char *ptr_max;
- register int num_quarks;
- register XrmBindingList t_bindings;
-
- int len, alloc_chars;
- unsigned long str_len;
- XrmValue value;
- Bool only_pcs;
- Bool dolines;
-
- if (!db)
- return;
-
- /*
- * if strlen (str) < DEF_BUFF_SIZE allocate buffers on the stack for
- * speed otherwise malloc the buffer. From a buffer overflow standpoint
- * we can be sure that neither: a) a component on the lhs, or b) a
- * value on the rhs, will be longer than the overall length of str,
- * i.e. strlen(str).
- *
- * This should give good performance when parsing "*foo: bar" type
- * databases as might be passed with -xrm command line options; but
- * with larger databases, e.g. .Xdefaults, app-defaults, or KeysymDB
- * files, the size of the buffers will be overly large. One way
- * around this would be to double-parse each production with a resulting
- * performance hit. In any event we can be assured that a lhs component
- * name or a rhs value won't be longer than str itself.
- */
-
- str_len = strlen (str);
- if (DEF_BUFF_SIZE > str_len) lhs = lhs_s;
- else if ((lhs = Xmalloc (str_len)) == NULL)
- return;
-
- alloc_chars = DEF_BUFF_SIZE < str_len ? str_len : DEF_BUFF_SIZE;
- if ((rhs = Xmalloc (alloc_chars)) == NULL) {
- if (lhs != lhs_s) Xfree (lhs);
- return;
- }
-
- (*db->methods->mbinit)(db->mbstate);
- str--;
- dolines = True;
- while (!is_EOF(bits) && dolines) {
- dolines = doall;
-
- /*
- * First: Remove extra whitespace.
- */
-
- do {
- bits = next_char(c, str);
- } while is_space(bits);
-
- /*
- * Ignore empty lines.
- */
-
- if (is_EOL(bits))
- continue; /* start a new line. */
-
- /*
- * Second: check the first character in a line to see if it is
- * "!" signifying a comment, or "#" signifying a directive.
- */
-
- if (c == '!') { /* Comment, spin to next newline */
- while (is_simple(bits = next_char(c, str))) {}
- if (is_EOL(bits))
- continue;
- while (!is_EOL(bits = next_mbchar(c, len, str))) {}
- str--;
- continue; /* start a new line. */
- }
-
- if (c == '#') { /* Directive */
- /* remove extra whitespace */
- only_pcs = True;
- while (is_space(bits = next_char(c, str))) {};
- /* only "include" directive is currently defined */
- if (!strncmp(str, "include", 7)) {
- str += (7-1);
- /* remove extra whitespace */
- while (is_space(bits = next_char(c, str))) {};
- /* must have a starting " */
- if (c == '"') {
- _Xconst char *fname = str+1;
- len = 0;
- do {
- if (only_pcs) {
- bits = next_char(c, str);
- if (is_nonpcs(bits))
- only_pcs = False;
- }
- if (!only_pcs)
- bits = next_mbchar(c, len, str);
- } while (c != '"' && !is_EOL(bits));
- /* must have an ending " */
- if (c == '"')
- GetIncludeFile(db, filename, fname, str - len - fname,
- depth);
- }
- }
- /* spin to next newline */
- if (only_pcs) {
- while (is_simple(bits))
- bits = next_char(c, str);
- if (is_EOL(bits))
- continue;
- }
- while (!is_EOL(bits))
- bits = next_mbchar(c, len, str);
- str--;
- continue; /* start a new line. */
- }
-
- /*
- * Third: loop through the LHS of the resource specification
- * storing characters and converting this to a Quark.
- */
-
- num_quarks = 0;
- t_bindings = bindings;
-
- sig = 0;
- ptr = lhs;
- *t_bindings = XrmBindTightly;
- for(;;) {
- if (!is_binding(bits)) {
- while (!is_EOQ(bits)) {
- *ptr++ = c;
- sig = (sig << 1) + c; /* Compute the signature. */
- bits = next_char(c, str);
- }
-
- quarks[num_quarks++] =
- _XrmInternalStringToQuark(lhs, ptr - lhs, sig, False);
-
- if (num_quarks > QLIST_SIZE) {
- Xfree(rhs);
- if (lhs != lhs_s) Xfree (lhs);
- (*db->methods->mbfinish)(db->mbstate);
- return;
- }
-
- if (is_separator(bits)) {
- if (!is_space(bits))
- break;
-
- /* Remove white space */
- do {
- *ptr++ = c;
- sig = (sig << 1) + c; /* Compute the signature. */
- } while (is_space(bits = next_char(c, str)));
-
- /*
- * The spec doesn't permit it, but support spaces
- * internal to resource name/class
- */
-
- if (is_separator(bits))
- break;
- num_quarks--;
- continue;
- }
-
- if (c == '.')
- *(++t_bindings) = XrmBindTightly;
- else
- *(++t_bindings) = XrmBindLoosely;
-
- sig = 0;
- ptr = lhs;
- }
- else {
- /*
- * Magic unspecified feature #254.
- *
- * If two separators appear with no Text between them then
- * ignore them.
- *
- * If anyone of those separators is a '*' then the binding
- * will be loose, otherwise it will be tight.
- */
-
- if (c == '*')
- *t_bindings = XrmBindLoosely;
- }
-
- bits = next_char(c, str);
- }
-
- quarks[num_quarks] = NULLQUARK;
-
- /*
- * Make sure that there is a ':' in this line.
- */
-
- if (c != ':') {
- char oldc;
-
- /*
- * A parsing error has occured, toss everything on the line
- * a new_line can still be escaped with a '\'.
- */
-
- while (is_normal(bits))
- bits = next_char(c, str);
- if (is_EOL(bits))
- continue;
- bits = next_mbchar(c, len, str);
- do {
- oldc = c;
- bits = next_mbchar(c, len, str);
- } while (c && (c != '\n' || oldc == '\\'));
- str--;
- continue;
- }
-
- /*
- * I now have a quark and binding list for the entire left hand
- * side. "c" currently points to the ":" separating the left hand
- * side for the right hand side. It is time to begin processing
- * the right hand side.
- */
-
- /*
- * Fourth: Remove more whitespace
- */
-
- for(;;) {
- if (is_space(bits = next_char(c, str)))
- continue;
- if (c != '\\')
- break;
- bits = next_char(c, str);
- if (c == '\n')
- continue;
- str--;
- bits = BSLASH;
- c = '\\';
- break;
- }
-
- /*
- * Fifth: Process the right hand side.
- */
-
- ptr = rhs;
- ptr_max = ptr + alloc_chars - 4;
- only_pcs = True;
- len = 1;
-
- for(;;) {
-
- /*
- * Tight loop for the normal case: Non backslash, non-end of value
- * character that will fit into the allocated buffer.
- */
-
- if (only_pcs) {
- while (is_normal(bits) && ptr < ptr_max) {
- *ptr++ = c;
- bits = next_char(c, str);
- }
- if (is_EOL(bits))
- break;
- if (is_nonpcs(bits)) {
- only_pcs = False;
- bits = next_mbchar(c, len, str);
- }
- }
- while (!is_special(bits) && ptr + len <= ptr_max) {
- len = -len;
- while (len)
- *ptr++ = str[len++];
- if (*str == '\0') {
- bits = EOS;
- break;
- }
- bits = next_mbchar(c, len, str);
- }
-
- if (is_EOL(bits)) {
- str--;
- break;
- }
-
- if (c == '\\') {
- /*
- * We need to do some magic after a backslash.
- */
- Bool read_next = True;
-
- if (only_pcs) {
- bits = next_char(c, str);
- if (is_nonpcs(bits))
- only_pcs = False;
- }
- if (!only_pcs)
- bits = next_mbchar(c, len, str);
-
- if (is_EOL(bits)) {
- if (is_EOF(bits))
- continue;
- } else if (c == 'n') {
- /*
- * "\n" means insert a newline.
- */
- *ptr++ = '\n';
- } else if (c == '\\') {
- /*
- * "\\" completes to just one backslash.
- */
- *ptr++ = '\\';
- } else {
- /*
- * pick up to three octal digits after the '\'.
- */
- char temp[3];
- int count = 0;
- while (is_odigit(bits) && count < 3) {
- temp[count++] = c;
- if (only_pcs) {
- bits = next_char(c, str);
- if (is_nonpcs(bits))
- only_pcs = False;
- }
- if (!only_pcs)
- bits = next_mbchar(c, len, str);
- }
-
- /*
- * If we found three digits then insert that octal code
- * into the value string as a character.
- */
-
- if (count == 3) {
- *ptr++ = (unsigned char) ((temp[0] - '0') * 0100 +
- (temp[1] - '0') * 010 +
- (temp[2] - '0'));
- }
- else {
- int tcount;
-
- /*
- * Otherwise just insert those characters into the
- * string, since no special processing is needed on
- * numerics we can skip the special processing.
- */
-
- for (tcount = 0; tcount < count; tcount++) {
- *ptr++ = temp[tcount]; /* print them in
- the correct order */
- }
- }
- read_next = False;
- }
- if (read_next) {
- if (only_pcs) {
- bits = next_char(c, str);
- if (is_nonpcs(bits))
- only_pcs = False;
- }
- if (!only_pcs)
- bits = next_mbchar(c, len, str);
- }
- }
-
- /*
- * It is important to make sure that there is room for at least
- * four more characters in the buffer, since I can add that
- * many characters into the buffer after a backslash has occured.
- */
-
- if (ptr + len > ptr_max) {
- char * temp_str;
-
- alloc_chars += BUFSIZ/10;
- temp_str = Xrealloc(rhs, sizeof(char) * alloc_chars);
-
- if (!temp_str) {
- Xfree(rhs);
- if (lhs != lhs_s) Xfree (lhs);
- (*db->methods->mbfinish)(db->mbstate);
- return;
- }
-
- ptr = temp_str + (ptr - rhs); /* reset pointer. */
- rhs = temp_str;
- ptr_max = rhs + alloc_chars - 4;
- }
- }
-
- /*
- * Lastly: Terminate the value string, and store this entry
- * into the database.
- */
-
- *ptr++ = '\0';
-
- /* Store it in database */
- value.size = ptr - rhs;
- value.addr = (XPointer) rhs;
-
- PutEntry(db, bindings, quarks, XrmQString, &value);
- }
-
- if (lhs != lhs_s) Xfree (lhs);
- Xfree (rhs);
-
- (*db->methods->mbfinish)(db->mbstate);
-}
-
-void
-XrmPutStringResource(
- XrmDatabase *pdb,
- _Xconst char*specifier,
- _Xconst char*str)
-{
- XrmValue value;
- XrmBinding bindings[MAXDBDEPTH+1];
- XrmQuark quarks[MAXDBDEPTH+1];
-
- if (!*pdb) *pdb = NewDatabase();
- XrmStringToBindingQuarkList(specifier, bindings, quarks);
- value.addr = (XPointer) str;
- value.size = strlen(str)+1;
- _XLockMutex(&(*pdb)->linfo);
- PutEntry(*pdb, bindings, quarks, XrmQString, &value);
- _XUnlockMutex(&(*pdb)->linfo);
-}
-
-
-void
-XrmPutLineResource(
- XrmDatabase *pdb,
- _Xconst char*line)
-{
- if (!*pdb) *pdb = NewDatabase();
- _XLockMutex(&(*pdb)->linfo);
- GetDatabase(*pdb, line, (char *)NULL, False, 0);
- _XUnlockMutex(&(*pdb)->linfo);
-}
-
-XrmDatabase
-XrmGetStringDatabase(
- _Xconst char *data)
-{
- XrmDatabase db;
-
- db = NewDatabase();
- _XLockMutex(&db->linfo);
- GetDatabase(db, data, (char *)NULL, True, 0);
- _XUnlockMutex(&db->linfo);
- return db;
-}
-
-/* Function Name: ReadInFile
- * Description: Reads the file into a buffer.
- * Arguments: filename - the name of the file.
- * Returns: An allocated string containing the contents of the file.
- */
-
-static char *
-ReadInFile(_Xconst char *filename)
-{
- register int fd, size;
- char * filebuf;
-
- /*
- * MS-Windows and OS/2 note: Default open mode includes O_TEXT
- */
- if ( (fd = _XOpenFile (filename, O_RDONLY)) == -1 )
- return (char *)NULL;
-
- /*
- * MS-Windows and OS/2 note: depending on how the sources are
- * untarred, the newlines in resource files may or may not have
- * been expanded to CRLF. Either way the size returned by fstat
- * is sufficient to read the file into because in text-mode any
- * CRLFs in a file will be converted to newlines (LF) with the
- * result that the number of bytes actually read with be <=
- * to the size returned by fstat.
- */
- {
- struct stat status_buffer;
- if ( ((fstat(fd, &status_buffer)) == -1 ) ||
- (status_buffer.st_size >= INT_MAX) ) {
- close (fd);
- return (char *)NULL;
- } else
- size = (int) status_buffer.st_size;
- }
-
- if (!(filebuf = Xmalloc(size + 1))) { /* leave room for '\0' */
- close(fd);
- return (char *)NULL;
- }
- size = read (fd, filebuf, size);
-
- if (size < 0) {
- close (fd);
- Xfree(filebuf);
- return (char *)NULL;
- }
- close (fd);
-
- filebuf[size] = '\0'; /* NULL terminate it. */
- return filebuf;
-}
-
-static void
-GetIncludeFile(
- XrmDatabase db,
- _Xconst char *base,
- _Xconst char *fname,
- int fnamelen,
- int depth)
-{
- int len;
- char *str;
- char realfname[BUFSIZ];
-
- if (fnamelen <= 0 || fnamelen >= BUFSIZ)
- return;
- if (depth >= MAXDBDEPTH)
- return;
- if (*fname != '/' && base && (str = strrchr(base, '/'))) {
- len = str - base + 1;
- if (len + fnamelen >= BUFSIZ)
- return;
- strncpy(realfname, base, len);
- strncpy(realfname + len, fname, fnamelen);
- realfname[len + fnamelen] = '\0';
- } else {
- strncpy(realfname, fname, fnamelen);
- realfname[fnamelen] = '\0';
- }
- if (!(str = ReadInFile(realfname)))
- return;
- GetDatabase(db, str, realfname, True, depth + 1);
- Xfree(str);
-}
-
-XrmDatabase
-XrmGetFileDatabase(
- _Xconst char *filename)
-{
- XrmDatabase db;
- char *str;
-
- if (!(str = ReadInFile(filename)))
- return (XrmDatabase)NULL;
-
- db = NewDatabase();
- _XLockMutex(&db->linfo);
- GetDatabase(db, str, filename, True, 0);
- _XUnlockMutex(&db->linfo);
- Xfree(str);
- return db;
-}
-
-Status
-XrmCombineFileDatabase(
- _Xconst char *filename,
- XrmDatabase *target,
- Bool override)
-{
- XrmDatabase db;
- char *str;
-
- if (!(str = ReadInFile(filename)))
- return 0;
- if (override) {
- db = *target;
- if (!db)
- *target = db = NewDatabase();
- } else
- db = NewDatabase();
- _XLockMutex(&db->linfo);
- GetDatabase(db, str, filename, True, 0);
- _XUnlockMutex(&db->linfo);
- Xfree(str);
- if (!override)
- XrmCombineDatabase(db, target, False);
- return 1;
-}
-
-/* call the user proc for every value in the table, arbitrary order.
- * stop if user proc returns True. level is current depth in database.
- */
-/*ARGSUSED*/
-static Bool EnumLTable(
- LTable table,
- XrmNameList names,
- XrmClassList classes,
- register int level,
- register EClosure closure)
-{
- register VEntry *bucket;
- register int i;
- register VEntry entry;
- XrmValue value;
- XrmRepresentation type;
- Bool tightOk;
-
- closure->bindings[level] = (table->table.tight ?
- XrmBindTightly : XrmBindLoosely);
- closure->quarks[level] = table->table.name;
- level++;
- tightOk = !*names;
- closure->quarks[level + 1] = NULLQUARK;
- for (i = table->table.mask, bucket = table->buckets;
- i >= 0;
- i--, bucket++) {
- for (entry = *bucket; entry; entry = entry->next) {
- if (entry->tight && !tightOk)
- continue;
- closure->bindings[level] = (entry->tight ?
- XrmBindTightly : XrmBindLoosely);
- closure->quarks[level] = entry->name;
- value.size = entry->size;
- if (entry->string) {
- type = XrmQString;
- value.addr = StringValue(entry);
- } else {
- type = RepType(entry);
- value.addr = DataValue(entry);
- }
- if ((*closure->proc)(&closure->db, closure->bindings+1,
- closure->quarks+1, &type, &value,
- closure->closure))
- return True;
- }
- }
- return False;
-}
-
-static Bool EnumAllNTable(
- NTable table,
- register int level,
- register EClosure closure)
-{
- register NTable *bucket;
- register int i;
- register NTable entry;
- XrmQuark empty = NULLQUARK;
-
- if (level >= MAXDBDEPTH)
- return False;
- for (i = table->mask, bucket = NodeBuckets(table);
- i >= 0;
- i--, bucket++) {
- for (entry = *bucket; entry; entry = entry->next) {
- if (entry->leaf) {
- if (EnumLTable((LTable)entry, &empty, &empty, level, closure))
- return True;
- } else {
- closure->bindings[level] = (entry->tight ?
- XrmBindTightly : XrmBindLoosely);
- closure->quarks[level] = entry->name;
- if (EnumAllNTable(entry, level+1, closure))
- return True;
- }
- }
- }
- return False;
-}
-
-/* recurse on every table in the table, arbitrary order.
- * stop if user proc returns True. level is current depth in database.
- */
-static Bool EnumNTable(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- register int level,
- register EClosure closure)
-{
- register NTable entry;
- register XrmQuark q;
- register unsigned int leaf;
- Bool (*get)(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- register int level,
- EClosure closure);
- Bool bilevel;
-
-/* find entries named ename, leafness leaf, tight or loose, and call get */
-#define ITIGHTLOOSE(ename) \
- NFIND(ename); \
- if (entry) { \
- if (leaf == entry->leaf) { \
- if (!leaf && !entry->tight && entry->next && \
- entry->next->name == q && entry->next->tight && \
- (bilevel || entry->next->hasloose) && \
- EnumLTable((LTable)entry->next, names+1, classes+1, \
- level, closure)) \
- return True; \
- if ((*get)(entry, names+1, classes+1, level, closure)) \
- return True; \
- if (entry->tight && (entry = entry->next) && \
- entry->name == q && leaf == entry->leaf && \
- (*get)(entry, names+1, classes+1, level, closure)) \
- return True; \
- } else if (entry->leaf) { \
- if ((bilevel || entry->hasloose) && \
- EnumLTable((LTable)entry, names+1, classes+1, level, closure))\
- return True; \
- if (entry->tight && (entry = entry->next) && \
- entry->name == q && (bilevel || entry->hasloose) && \
- EnumLTable((LTable)entry, names+1, classes+1, level, closure))\
- return True; \
- } \
- }
-
-/* find entries named ename, leafness leaf, loose only, and call get */
-#define ILOOSE(ename) \
- NFIND(ename); \
- if (entry && entry->tight && (entry = entry->next) && entry->name != q) \
- entry = (NTable)NULL; \
- if (entry) { \
- if (leaf == entry->leaf) { \
- if ((*get)(entry, names+1, classes+1, level, closure)) \
- return True; \
- } else if (entry->leaf && (bilevel || entry->hasloose)) { \
- if (EnumLTable((LTable)entry, names+1, classes+1, level, closure))\
- return True; \
- } \
- }
-
- if (level >= MAXDBDEPTH)
- return False;
- closure->bindings[level] = (table->tight ?
- XrmBindTightly : XrmBindLoosely);
- closure->quarks[level] = table->name;
- level++;
- if (!*names) {
- if (EnumAllNTable(table, level, closure))
- return True;
- } else {
- if (names[1] || closure->mode == XrmEnumAllLevels) {
- get = EnumNTable; /* recurse */
- leaf = 0;
- bilevel = !names[1];
- } else {
- get = (getNTableEProcp)EnumLTable; /* bottom of recursion */
- leaf = 1;
- bilevel = False;
- }
- if (table->hasloose && closure->mode == XrmEnumAllLevels) {
- NTable *bucket;
- int i;
- XrmQuark empty = NULLQUARK;
-
- for (i = table->mask, bucket = NodeBuckets(table);
- i >= 0;
- i--, bucket++) {
- q = NULLQUARK;
- for (entry = *bucket; entry; entry = entry->next) {
- if (!entry->tight && entry->name != q &&
- entry->name != *names && entry->name != *classes) {
- q = entry->name;
- if (entry->leaf) {
- if (EnumLTable((LTable)entry, &empty, &empty,
- level, closure))
- return True;
- } else {
- if (EnumNTable(entry, &empty, &empty,
- level, closure))
- return True;
- }
- }
- }
- }
- }
-
- ITIGHTLOOSE(*names); /* do name, tight and loose */
- ITIGHTLOOSE(*classes); /* do class, tight and loose */
- if (table->hasany) {
- ITIGHTLOOSE(XrmQANY); /* do ANY, tight and loose */
- }
- if (table->hasloose) {
- while (1) {
- names++;
- classes++;
- if (!*names)
- break;
- if (!names[1] && closure->mode != XrmEnumAllLevels) {
- get = (getNTableEProcp)EnumLTable; /* bottom of recursion */
- leaf = 1;
- }
- ILOOSE(*names); /* loose names */
- ILOOSE(*classes); /* loose classes */
- if (table->hasany) {
- ILOOSE(XrmQANY); /* loose ANY */
- }
- }
- names--;
- classes--;
- }
- }
- /* now look for matching leaf nodes */
- entry = table->next;
- if (!entry)
- return False;
- if (entry->leaf) {
- if (entry->tight && !table->tight)
- entry = entry->next;
- } else {
- entry = entry->next;
- if (!entry || !entry->tight)
- return False;
- }
- if (!entry || entry->name != table->name)
- return False;
- /* found one */
- level--;
- if ((!*names || entry->hasloose) &&
- EnumLTable((LTable)entry, names, classes, level, closure))
- return True;
- if (entry->tight && entry == table->next && (entry = entry->next) &&
- entry->name == table->name && (!*names || entry->hasloose))
- return EnumLTable((LTable)entry, names, classes, level, closure);
- return False;
-
-#undef ITIGHTLOOSE
-#undef ILOOSE
-}
-
-/* call the proc for every value in the database, arbitrary order.
- * stop if the proc returns True.
- */
-Bool XrmEnumerateDatabase(
- XrmDatabase db,
- XrmNameList names,
- XrmClassList classes,
- int mode,
- DBEnumProc proc,
- XPointer closure)
-{
- XrmBinding bindings[MAXDBDEPTH+2];
- XrmQuark quarks[MAXDBDEPTH+2];
- register NTable table;
- EClosureRec eclosure;
- Bool retval = False;
-
- if (!db)
- return False;
- _XLockMutex(&db->linfo);
- eclosure.db = db;
- eclosure.proc = proc;
- eclosure.closure = closure;
- eclosure.bindings = bindings;
- eclosure.quarks = quarks;
- eclosure.mode = mode;
- table = db->table;
- if (table && !table->leaf && !*names && mode == XrmEnumOneLevel)
- table = table->next;
- if (table) {
- if (!table->leaf)
- retval = EnumNTable(table, names, classes, 0, &eclosure);
- else
- retval = EnumLTable((LTable)table, names, classes, 0, &eclosure);
- }
- _XUnlockMutex(&db->linfo);
- return retval;
-}
-
-static void PrintBindingQuarkList(
- XrmBindingList bindings,
- XrmQuarkList quarks,
- FILE *stream)
-{
- Bool firstNameSeen;
-
- for (firstNameSeen = False; *quarks; bindings++, quarks++) {
- if (*bindings == XrmBindLoosely) {
- (void) fprintf(stream, "*");
- } else if (firstNameSeen) {
- (void) fprintf(stream, ".");
- }
- firstNameSeen = True;
- (void) fputs(XrmQuarkToString(*quarks), stream);
- }
-}
-
-/* output out the entry in correct file syntax */
-/*ARGSUSED*/
-static Bool DumpEntry(
- XrmDatabase *db,
- XrmBindingList bindings,
- XrmQuarkList quarks,
- XrmRepresentation *type,
- XrmValuePtr value,
- XPointer data)
-{
- FILE *stream = (FILE *)data;
- register unsigned int i;
- register char *s;
- register char c;
-
- if (*type != XrmQString)
- (void) putc('!', stream);
- PrintBindingQuarkList(bindings, quarks, stream);
- s = value->addr;
- i = value->size;
- if (*type == XrmQString) {
- (void) fputs(":\t", stream);
- if (i)
- i--;
- }
- else
- (void) fprintf(stream, "=%s:\t", XrmRepresentationToString(*type));
- if (i && (*s == ' ' || *s == '\t'))
- (void) putc('\\', stream); /* preserve leading whitespace */
- while (i--) {
- c = *s++;
- if (c == '\n') {
- if (i)
- (void) fputs("\\n\\\n", stream);
- else
- (void) fputs("\\n", stream);
- } else if (c == '\\')
- (void) fputs("\\\\", stream);
- else if ((c < ' ' && c != '\t') ||
- ((unsigned char)c >= 0x7f && (unsigned char)c < 0xa0))
- (void) fprintf(stream, "\\%03o", (unsigned char)c);
- else
- (void) putc(c, stream);
- }
- (void) putc('\n', stream);
- return ferror(stream) != 0;
-}
-
-#ifdef DEBUG
-
-void PrintTable(
- NTable table,
- FILE *file)
-{
- XrmBinding bindings[MAXDBDEPTH+1];
- XrmQuark quarks[MAXDBDEPTH+1];
- EClosureRec closure;
- XrmQuark empty = NULLQUARK;
-
- closure.db = (XrmDatabase)NULL;
- closure.proc = DumpEntry;
- closure.closure = (XPointer)file;
- closure.bindings = bindings;
- closure.quarks = quarks;
- closure.mode = XrmEnumAllLevels;
- if (table->leaf)
- EnumLTable((LTable)table, &empty, &empty, 0, &closure);
- else
- EnumNTable(table, &empty, &empty, 0, &closure);
-}
-
-#endif /* DEBUG */
-
-void
-XrmPutFileDatabase(
- XrmDatabase db,
- _Xconst char *fileName)
-{
- FILE *file;
- XrmQuark empty = NULLQUARK;
-
- if (!db) return;
- if (!(file = fopen(fileName, "w"))) return;
- if (XrmEnumerateDatabase(db, &empty, &empty, XrmEnumAllLevels,
- DumpEntry, (XPointer) file))
- unlink((char *)fileName);
- fclose(file);
-}
-
-/* macros used in get/search functions */
-
-/* find entries named ename, leafness leaf, tight or loose, and call get */
-#define GTIGHTLOOSE(ename,looseleaf) \
- NFIND(ename); \
- if (entry) { \
- if (leaf == entry->leaf) { \
- if (!leaf && !entry->tight && entry->next && \
- entry->next->name == q && entry->next->tight && \
- entry->next->hasloose && \
- looseleaf((LTable)entry->next, names+1, classes+1, closure)) \
- return True; \
- if ((*get)(entry, names+1, classes+1, closure)) \
- return True; \
- if (entry->tight && (entry = entry->next) && \
- entry->name == q && leaf == entry->leaf && \
- (*get)(entry, names+1, classes+1, closure)) \
- return True; \
- } else if (entry->leaf) { \
- if (entry->hasloose && \
- looseleaf((LTable)entry, names+1, classes+1, closure)) \
- return True; \
- if (entry->tight && (entry = entry->next) && \
- entry->name == q && entry->hasloose && \
- looseleaf((LTable)entry, names+1, classes+1, closure)) \
- return True; \
- } \
- }
-
-/* find entries named ename, leafness leaf, loose only, and call get */
-#define GLOOSE(ename,looseleaf) \
- NFIND(ename); \
- if (entry && entry->tight && (entry = entry->next) && entry->name != q) \
- entry = (NTable)NULL; \
- if (entry) { \
- if (leaf == entry->leaf) { \
- if ((*get)(entry, names+1, classes+1, closure)) \
- return True; \
- } else if (entry->leaf && entry->hasloose) { \
- if (looseleaf((LTable)entry, names+1, classes+1, closure)) \
- return True; \
- } \
- }
-
-/* add tight/loose entry to the search list, return True if list is full */
-/*ARGSUSED*/
-static Bool AppendLEntry(
- LTable table,
- XrmNameList names,
- XrmClassList classes,
- register SClosure closure)
-{
- /* check for duplicate */
- if (closure->idx >= 0 && closure->list[closure->idx] == table)
- return False;
- if (closure->idx == closure->limit)
- return True;
- /* append it */
- closure->idx++;
- closure->list[closure->idx] = table;
- return False;
-}
-
-/* add loose entry to the search list, return True if list is full */
-/*ARGSUSED*/
-static Bool AppendLooseLEntry(
- LTable table,
- XrmNameList names,
- XrmClassList classes,
- register SClosure closure)
-{
- /* check for duplicate */
- if (closure->idx >= 0 && closure->list[closure->idx] == table)
- return False;
- if (closure->idx >= closure->limit - 1)
- return True;
- /* append it */
- closure->idx++;
- closure->list[closure->idx] = LOOSESEARCH;
- closure->idx++;
- closure->list[closure->idx] = table;
- return False;
-}
-
-/* search for a leaf table */
-static Bool SearchNEntry(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- SClosure closure)
-{
- register NTable entry;
- register XrmQuark q;
- register unsigned int leaf;
- Bool (*get)(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- SClosure closure);
-
- if (names[1]) {
- get = SearchNEntry; /* recurse */
- leaf = 0;
- } else {
- get = (getNTableSProcp)AppendLEntry; /* bottom of recursion */
- leaf = 1;
- }
- GTIGHTLOOSE(*names, AppendLooseLEntry); /* do name, tight and loose */
- GTIGHTLOOSE(*classes, AppendLooseLEntry); /* do class, tight and loose */
- if (table->hasany) {
- GTIGHTLOOSE(XrmQANY, AppendLooseLEntry); /* do ANY, tight and loose */
- }
- if (table->hasloose) {
- while (1) {
- names++;
- classes++;
- if (!*names)
- break;
- if (!names[1]) {
- get = (getNTableSProcp)AppendLEntry; /* bottom of recursion */
- leaf = 1;
- }
- GLOOSE(*names, AppendLooseLEntry); /* loose names */
- GLOOSE(*classes, AppendLooseLEntry); /* loose classes */
- if (table->hasany) {
- GLOOSE(XrmQANY, AppendLooseLEntry); /* loose ANY */
- }
- }
- }
- /* now look for matching leaf nodes */
- entry = table->next;
- if (!entry)
- return False;
- if (entry->leaf) {
- if (entry->tight && !table->tight)
- entry = entry->next;
- } else {
- entry = entry->next;
- if (!entry || !entry->tight)
- return False;
- }
- if (!entry || entry->name != table->name)
- return False;
- /* found one */
- if (entry->hasloose &&
- AppendLooseLEntry((LTable)entry, names, classes, closure))
- return True;
- if (entry->tight && entry == table->next && (entry = entry->next) &&
- entry->name == table->name && entry->hasloose)
- return AppendLooseLEntry((LTable)entry, names, classes, closure);
- return False;
-}
-
-Bool XrmQGetSearchList(
- XrmDatabase db,
- XrmNameList names,
- XrmClassList classes,
- XrmSearchList searchList, /* RETURN */
- int listLength)
-{
- register NTable table;
- SClosureRec closure;
-
- if (listLength <= 0)
- return False;
- closure.list = (LTable *)searchList;
- closure.idx = -1;
- closure.limit = listLength - 2;
- if (db) {
- _XLockMutex(&db->linfo);
- table = db->table;
- if (*names) {
- if (table && !table->leaf) {
- if (SearchNEntry(table, names, classes, &closure)) {
- _XUnlockMutex(&db->linfo);
- return False;
- }
- } else if (table && table->hasloose &&
- AppendLooseLEntry((LTable)table, names, classes,
- &closure)) {
- _XUnlockMutex(&db->linfo);
- return False;
- }
- } else {
- if (table && !table->leaf)
- table = table->next;
- if (table &&
- AppendLEntry((LTable)table, names, classes, &closure)) {
- _XUnlockMutex(&db->linfo);
- return False;
- }
- }
- _XUnlockMutex(&db->linfo);
- }
- closure.list[closure.idx + 1] = (LTable)NULL;
- return True;
-}
-
-Bool XrmQGetSearchResource(
- XrmSearchList searchList,
- register XrmName name,
- register XrmClass class,
- XrmRepresentation *pType, /* RETURN */
- XrmValue *pValue) /* RETURN */
-{
- register LTable *list;
- register LTable table;
- register VEntry entry = NULL;
- int flags;
-
-/* find tight or loose entry */
-#define VTIGHTLOOSE(q) \
- entry = LeafHash(table, q); \
- while (entry && entry->name != q) \
- entry = entry->next; \
- if (entry) \
- break
-
-/* find loose entry */
-#define VLOOSE(q) \
- entry = LeafHash(table, q); \
- while (entry && entry->name != q) \
- entry = entry->next; \
- if (entry) { \
- if (!entry->tight) \
- break; \
- if ((entry = entry->next) && entry->name == q) \
- break; \
- }
-
- list = (LTable *)searchList;
- /* figure out which combination of name and class we need to search for */
- flags = 0;
- if (IsResourceQuark(name))
- flags = 2;
- if (IsResourceQuark(class))
- flags |= 1;
- if (!flags) {
- /* neither name nor class has ever been used to name a resource */
- table = (LTable)NULL;
- } else if (flags == 3) {
- /* both name and class */
- while ((table = *list++)) {
- if (table != LOOSESEARCH) {
- VTIGHTLOOSE(name); /* do name, tight and loose */
- VTIGHTLOOSE(class); /* do class, tight and loose */
- } else {
- table = *list++;
- VLOOSE(name); /* do name, loose only */
- VLOOSE(class); /* do class, loose only */
- }
- }
- } else {
- /* just one of name or class */
- if (flags == 1)
- name = class;
- while ((table = *list++)) {
- if (table != LOOSESEARCH) {
- VTIGHTLOOSE(name); /* tight and loose */
- } else {
- table = *list++;
- VLOOSE(name); /* loose only */
- }
- }
- }
- if (table) {
- /* found a match */
- if (entry->string) {
- *pType = XrmQString;
- pValue->addr = StringValue(entry);
- } else {
- *pType = RepType(entry);
- pValue->addr = DataValue(entry);
- }
- pValue->size = entry->size;
- return True;
- }
- *pType = NULLQUARK;
- pValue->addr = (XPointer)NULL;
- pValue->size = 0;
- return False;
-
-#undef VTIGHTLOOSE
-#undef VLOOSE
-}
-
-/* look for a tight/loose value */
-static Bool GetVEntry(
- LTable table,
- XrmNameList names,
- XrmClassList classes,
- VClosure closure)
-{
- register VEntry entry;
- register XrmQuark q;
-
- /* try name first */
- q = *names;
- entry = LeafHash(table, q);
- while (entry && entry->name != q)
- entry = entry->next;
- if (!entry) {
- /* not found, try class */
- q = *classes;
- entry = LeafHash(table, q);
- while (entry && entry->name != q)
- entry = entry->next;
- if (!entry)
- return False;
- }
- if (entry->string) {
- *closure->type = XrmQString;
- closure->value->addr = StringValue(entry);
- } else {
- *closure->type = RepType(entry);
- closure->value->addr = DataValue(entry);
- }
- closure->value->size = entry->size;
- return True;
-}
-
-/* look for a loose value */
-static Bool GetLooseVEntry(
- LTable table,
- XrmNameList names,
- XrmClassList classes,
- VClosure closure)
-{
- register VEntry entry;
- register XrmQuark q;
-
-#define VLOOSE(ename) \
- q = ename; \
- entry = LeafHash(table, q); \
- while (entry && entry->name != q) \
- entry = entry->next; \
- if (entry && entry->tight && (entry = entry->next) && entry->name != q) \
- entry = (VEntry)NULL;
-
- /* bump to last component */
- while (names[1]) {
- names++;
- classes++;
- }
- VLOOSE(*names); /* do name, loose only */
- if (!entry) {
- VLOOSE(*classes); /* do class, loose only */
- if (!entry)
- return False;
- }
- if (entry->string) {
- *closure->type = XrmQString;
- closure->value->addr = StringValue(entry);
- } else {
- *closure->type = RepType(entry);
- closure->value->addr = DataValue(entry);
- }
- closure->value->size = entry->size;
- return True;
-
-#undef VLOOSE
-}
-
-/* recursive search for a value */
-static Bool GetNEntry(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- VClosure closure)
-{
- register NTable entry;
- register XrmQuark q;
- register unsigned int leaf;
- Bool (*get)(
- NTable table,
- XrmNameList names,
- XrmClassList classes,
- VClosure closure);
- NTable otable;
-
- if (names[2]) {
- get = GetNEntry; /* recurse */
- leaf = 0;
- } else {
- get = (getNTableVProcp)GetVEntry; /* bottom of recursion */
- leaf = 1;
- }
- GTIGHTLOOSE(*names, GetLooseVEntry); /* do name, tight and loose */
- GTIGHTLOOSE(*classes, GetLooseVEntry); /* do class, tight and loose */
- if (table->hasany) {
- GTIGHTLOOSE(XrmQANY, GetLooseVEntry); /* do ANY, tight and loose */
- }
- if (table->hasloose) {
- while (1) {
- names++;
- classes++;
- if (!names[1])
- break;
- if (!names[2]) {
- get = (getNTableVProcp)GetVEntry; /* bottom of recursion */
- leaf = 1;
- }
- GLOOSE(*names, GetLooseVEntry); /* do name, loose only */
- GLOOSE(*classes, GetLooseVEntry); /* do class, loose only */
- if (table->hasany) {
- GLOOSE(XrmQANY, GetLooseVEntry); /* do ANY, loose only */
- }
- }
- }
- /* look for matching leaf tables */
- otable = table;
- table = table->next;
- if (!table)
- return False;
- if (table->leaf) {
- if (table->tight && !otable->tight)
- table = table->next;
- } else {
- table = table->next;
- if (!table || !table->tight)
- return False;
- }
- if (!table || table->name != otable->name)
- return False;
- /* found one */
- if (table->hasloose &&
- GetLooseVEntry((LTable)table, names, classes, closure))
- return True;
- if (table->tight && table == otable->next) {
- table = table->next;
- if (table && table->name == otable->name && table->hasloose)
- return GetLooseVEntry((LTable)table, names, classes, closure);
- }
- return False;
-}
-
-Bool XrmQGetResource(
- XrmDatabase db,
- XrmNameList names,
- XrmClassList classes,
- XrmRepresentation *pType, /* RETURN */
- XrmValuePtr pValue) /* RETURN */
-{
- register NTable table;
- VClosureRec closure;
-
- if (db && *names) {
- _XLockMutex(&db->linfo);
- closure.type = pType;
- closure.value = pValue;
- table = db->table;
- if (names[1]) {
- if (table && !table->leaf) {
- if (GetNEntry(table, names, classes, &closure)) {
- _XUnlockMutex(&db->linfo);
- return True;
- }
- } else if (table && table->hasloose &&
- GetLooseVEntry((LTable)table, names, classes, &closure)) {
- _XUnlockMutex (&db->linfo);
- return True;
- }
- } else {
- if (table && !table->leaf)
- table = table->next;
- if (table && GetVEntry((LTable)table, names, classes, &closure)) {
- _XUnlockMutex(&db->linfo);
- return True;
- }
- }
- _XUnlockMutex(&db->linfo);
- }
- *pType = NULLQUARK;
- pValue->addr = (XPointer)NULL;
- pValue->size = 0;
- return False;
-}
-
-Bool
-XrmGetResource(XrmDatabase db, _Xconst char *name_str, _Xconst char *class_str,
- XrmString *pType_str, XrmValuePtr pValue)
-{
- XrmName names[MAXDBDEPTH+1];
- XrmClass classes[MAXDBDEPTH+1];
- XrmRepresentation fromType;
- Bool result;
-
- XrmStringToNameList(name_str, names);
- XrmStringToClassList(class_str, classes);
- result = XrmQGetResource(db, names, classes, &fromType, pValue);
- (*pType_str) = XrmQuarkToString(fromType);
- return result;
-}
-
-/* destroy all values, plus table itself */
-static void DestroyLTable(
- LTable table)
-{
- register int i;
- register VEntry *buckets;
- register VEntry entry, next;
-
- buckets = table->buckets;
- for (i = table->table.mask; i >= 0; i--, buckets++) {
- for (next = *buckets; (entry = next); ) {
- next = entry->next;
- Xfree(entry);
- }
- }
- Xfree(table->buckets);
- Xfree(table);
-}
-
-/* destroy all contained tables, plus table itself */
-static void DestroyNTable(
- NTable table)
-{
- register int i;
- register NTable *buckets;
- register NTable entry, next;
-
- buckets = NodeBuckets(table);
- for (i = table->mask; i >= 0; i--, buckets++) {
- for (next = *buckets; (entry = next); ) {
- next = entry->next;
- if (entry->leaf)
- DestroyLTable((LTable)entry);
- else
- DestroyNTable(entry);
- }
- }
- Xfree(table);
-}
-
-const char *
-XrmLocaleOfDatabase(
- XrmDatabase db)
-{
- const char* retval;
- _XLockMutex(&db->linfo);
- retval = (*db->methods->lcname)(db->mbstate);
- _XUnlockMutex(&db->linfo);
- return retval;
-}
-
-void XrmDestroyDatabase(
- XrmDatabase db)
-{
- register NTable table, next;
-
- if (db) {
- _XLockMutex(&db->linfo);
- for (next = db->table; (table = next); ) {
- next = table->next;
- if (table->leaf)
- DestroyLTable((LTable)table);
- else
- DestroyNTable(table);
- }
- _XUnlockMutex(&db->linfo);
- _XFreeMutex(&db->linfo);
- (*db->methods->destroy)(db->mbstate);
- Xfree(db);
- }
-}