/nx-3.5.0/nx-X11/lib/X11/Xrm.c
C | 2663 lines | 2203 code | 154 blank | 306 comment | 402 complexity | e9249c5fef02b25c787573cc93125518 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- /* $Xorg: Xrm.c,v 1.7 2001/02/09 02:03:39 xorgcvs Exp $ */
- /***********************************************************
- 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.
- */
- /* $XFree86: xc/lib/X11/Xrm.c,v 3.22 2003/07/16 01:38:26 dawes Exp $ */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- #include <stdio.h>
- #include <ctype.h>
- #include "Xlibint.h"
- #include <X11/Xresource.h>
- #include "Xlcint.h"
- #ifdef XTHREADS
- #include "locking.h"
- #endif
- #include "XrmI.h"
- #include <X11/Xos.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) || defined(__UNIXOS2__)
- 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("?");
- }
- #ifndef _XP_PRINT_SERVER_
- 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 imlicitely by XGetDefault() */
- if (display->db && (display->flags & XlibDisplayDfltRMDB)) {
- XrmDestroyDatabase(display->db);
- display->flags &= ~XlibDisplayDfltRMDB;
- }
- display->db = database;
- UnlockDisplay(display);
- }
- #endif /* !_XP_PRINT_SERVER_ */
- 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 = (XrmDatabase) Xmalloc(sizeof(XrmHashBucketRec));
- if (db) {
- _XCreateMutex(&db->linfo);
- db->table = (NTable)NULL;
- db->mbstate = (XPointer)NULL;
- #ifdef _XP_PRINT_SERVER_
- db->methods = NULL;
- #else
- db->methods = _XrmInitParseInfo(&db->mbstate);
- #endif
- if (!db->methods)
- db->methods = &mb_methods;
- }
- return db;
- }
- /* move all values from ftable to ttable, and free ftable's buckets.
- * ttable is quaranteed 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((char *)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((char *)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 = (VEntry *)Xmalloc(i * sizeof(VEntry));
- if (!ltable->buckets) {
- ltable->buckets = otable.buckets;
- return;
- }
- ltable->table.mask = i - 1;
- bzero((char *)ltable->buckets, i * sizeof(VEntry));
- MoveValues(&otable, ltable);
- } else {
- register NTable ntable;
- ntable = (NTable)Xmalloc(sizeof(NTableRec) + i * sizeof(NTable));
- if (!ntable)
- return;
- *ntable = *table;
- ntable->mask = i - 1;
- bzero((char *)NodeBuckets(ntable), i * sizeof(NTable));
- *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((char *)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((char *)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((char *)ftable->buckets);
- Xfree((char *)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((char *)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);
- _XFreeMutex(&from->linfo);
- Xfree((char *)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 = (NTable)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 = (NTable *)Xmalloc(sizeof(VEntry *)))) \
- 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((char *)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 = (VEntry)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 = (unsigned char *)Xrealloc((char *)resourceQuarks,
- size);
- if (!resourceQuarks) {
- Xfree(prevQuarks);
- }
- } else
- resourceQuarks = (unsigned char *)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);
- static void GetDatabase(
- XrmDatabase db,
- _Xconst register char *str,
- _Xconst char *filename,
- Bool doall)
- {
- 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 = (char*) Xmalloc (str_len)) == NULL)
- return;
- alloc_chars = DEF_BUFF_SIZE < str_len ? str_len : DEF_BUFF_SIZE;
- if ((rhs = (char*) 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);
- }
- }
- /* 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);
- _XUnlockMutex(&(*pdb)->linfo);
- }
- XrmDatabase
- XrmGetStringDatabase(
- _Xconst char *data)
- {
- XrmDatabase db;
- db = NewDatabase();
- _XLockMutex(&db->linfo);
- GetDatabase(db, data, (char *)NULL, True);
- _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;
- #ifdef __UNIXOS2__
- filename = __XOS2RedirRoot(filename);
- #endif
- /*
- * 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.
- */
- GetSizeOfFile(fd, size);
- if (!(filebuf = Xmalloc(size + 1))) { /* leave room for '\0' */
- close(fd);
- return (char *)NULL;
- }
- size = read (fd, filebuf, size);
- #ifdef __UNIXOS2__
- { /* kill CRLF */
- int i,k;
- for (i=k=0; i<size; i++)
- if (filebuf[i] != 0x0d) {
- filebuf[k++] = filebuf[i];
- }
- filebuf[k] = 0;
- }
- #endif
- 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 len;
- char *str;
- char realfname[BUFSIZ];
- if (fnamelen <= 0 || fnamelen >= BUFSIZ)
- 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);
- 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);
- _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);
- _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;
- …
Large files files are truncated, but you can click here to view the full file