#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"
static XrmQuark XrmQString, XrmQANY;
typedef Bool (*DBEnumProc)(
XrmDatabase* ,
XrmBindingList ,
XrmQuarkList ,
XrmRepresentation* ,
XrmValue* ,
XPointer
);
typedef struct _VEntry {
struct _VEntry *next;
XrmQuark name;
unsigned int tight:1;
unsigned int string:1;
unsigned int size:30;
} VEntryRec, *VEntry;
typedef struct _DEntry {
VEntryRec entry;
XrmRepresentation type;
} DEntryRec, *DEntry;
#define StringValue(ve) (XPointer)((ve) + 1)
#define RepType(ve) ((DEntry)(ve))->type
#define DataValue(ve) (XPointer)(((DEntry)(ve)) + 1)
#define RawValue(ve) (char *)((ve)->string ? StringValue(ve) : DataValue(ve))
typedef struct _NTable {
struct _NTable *next;
XrmQuark name;
unsigned int tight:1;
unsigned int leaf:1;
unsigned int hasloose:1;
unsigned int hasany:1;
unsigned int pad:4;
unsigned int mask:8;
unsigned int entries:16;
} NTableRec, *NTable;
#define NodeBuckets(ne) ((NTable *)((ne) + 1))
#define NodeHash(ne,q) NodeBuckets(ne)[(q) & (ne)->mask]
typedef struct _LTable {
NTableRec table;
VEntry *buckets;
} LTableRec, *LTable;
#define LeafHash(le,q) (le)->buckets[(q) & (le)->table.mask]
typedef struct _XrmHashBucketRec {
NTable table;
XPointer mbstate;
XrmMethods methods;
#ifdef XTHREADS
LockInfoRec linfo;
#endif
} XrmHashBucketRec;
typedef struct _VClosure {
XrmRepresentation *type;
XrmValuePtr value;
} VClosureRec, *VClosure;
typedef struct _SClosure {
LTable *list;
int idx;
int limit;
} SClosureRec, *SClosure;
#define LOOSESEARCH ((LTable)1)
typedef struct _EClosure {
XrmDatabase db;
DBEnumProc proc;
XPointer closure;
XrmBindingList bindings;
XrmQuarkList quarks;
int mode;
} EClosureRec, *EClosure;
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);
#define GrowthPred(n,m) ((unsigned)(n) > (((m) + 1) << 2))
#define GROW(prev) \
if (GrowthPred((*prev)->entries, (*prev)->mask)) \
GrowTable(prev)
#define MAXDBDEPTH 100
#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; \
}
static unsigned char *resourceQuarks = (unsigned char *)NULL;
static XrmQuark maxResourceQuark = -1;
#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))
static XrmBits const xrmtypes[256] = {
EOS,0,0,0,0,0,0,0,
0,SPACE,EOL,0,0,
#if defined(WIN32) || defined(__UNIXOS2__)
EOL,
#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
};
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);
if (display->db && (display->flags & XlibDisplayDfltRMDB)) {
XrmDestroyDatabase(display->db);
display->flags &= ~XlibDisplayDfltRMDB;
}
display->db = database;
UnlockDisplay(display);
}
#endif
void
XrmStringToQuarkList(
register _Xconst char *name,
register XrmQuarkList quarks)
{
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) {
*quarks++ = _XrmInternalStringToQuark(name,tname - name,
sig, False);
i = 0;
sig = 0;
}
name = tname+1;
}
else {
sig = (sig << 1) + ch;
i++;
}
}
*quarks++ = _XrmInternalStringToQuark(name, tname - name, sig, False);
}
*quarks = NULLQUARK;
}
void
XrmStringToBindingQuarkList(
register _Xconst char *name,
register XrmBindingList bindings,
register XrmQuarkList quarks)
{
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) {
*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;
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);
}
}
#endif
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,
c_mbchar,
c_mbnoop,
c_lcname,
c_mbnoop
};
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;
}
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;
while ((nfentry = fentry->next) && nfentry->name == fentry->name)
fentry = nfentry;
fentry->next = tentry;
}
}
Xfree((char *)ftable->buckets);
}
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;
while ((nfentry = fentry->next) && nfentry->name == fentry->name)
fentry = nfentry;
fentry->next = tentry;
}
}
Xfree((char *)ftable);
}
static void GrowTable(
NTable *prev)
{
register NTable table;
register int i;
table = *prev;
i = table->mask;
if (i == 255)
return;
while (i < 255 && GrowthPred(table->entries, i))
i = (i << 1) + 1;
i++;
if (table->leaf) {
register LTable ltable;
LTableRec otable;
ltable = (LTable)table;
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);
}
}
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);
while (tentry && tentry->name == fentry->name) {
if (!fentry->tight && tentry->tight) {
tentry = *(prev = &tentry->next);
continue;
}
if (fentry->tight != tentry->tight) {
*prev = fentry;
prev = &fentry->next;
fentry = *prev;
*prev = tentry;
ttable->table.entries++;
} else if (override) {
*prev = fentry;
prev = &fentry->next;
fentry = *prev;
*prev = tentry->next;
Xfree((char *)tentry);
tentry = *prev;
} else {
prev = &tentry->next;
tentry = fentry;
fentry = fentry->next;
Xfree((char *)tentry);
tentry = *prev;
}
if (!fentry)
break;
}
while (fentry && fentry->name == q) {
*prev = fentry;
prev = &fentry->next;
fentry = *prev;
*prev = tentry;
ttable->table.entries++;
}
}
}
Xfree((char *)ftable->buckets);
Xfree((char *)ftable);
GROW(pprev);
}
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);
while (tentry && tentry->name == fentry->name) {
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) {
*prev = fentry;
*(prev = &fentry->next) = tentry;
ttable->entries++;
} else {
if (fentry->leaf)
MergeValues((LTable)fentry, prev, override);
else
MergeTables(fentry, prev, override);
tentry = *(prev = &(*prev)->next);
}
fentry = nfentry;
if (!fentry)
break;
}
while (fentry && fentry->name == q) {
*prev = fentry;
prev = &fentry->next;
fentry = *prev;
*prev = tentry;
ttable->entries++;
}
}
}
Xfree((char *)ftable);
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) {
MergeTables(ftable, prev, override);
ttable = *(prev = &(*prev)->next);
} else {
*prev = ftable;
*(prev = &ftable->next) = ttable;
}
ftable = nftable;
} else {
if (ttable && !ttable->leaf)
ttable = *(prev = &ttable->next);
}
if (ftable) {
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);
}
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 (!quarks[1] && table && !table->leaf)
table = *(prev = &table->next);
pprev = prev;
if (!table || (quarks[1] && table->leaf)) {
NEWTABLE(NULLQUARK,1);
table->tight = 1;
prev = nprev;
} else {
while (quarks[1]) {
q = *quarks;
table = *(prev = &NodeHash(table, q));
while (table && table->name != q)
table = *(prev = &table->next);
if (!table)
break;
if (quarks[2]) {
if (table->leaf)
break;
} else {
if (!table->leaf) {
table = *(prev = &table->next);
if (!table || table->name != q)
break;
if (!table->leaf) {
table = *(prev = &table->next);
if (!table || table->name != q)
break;
}
}
}
if (*bindings == XrmBindTightly) {
if (!table->tight)
break;
} else {
if (table->tight) {
table = *(prev = &table->next);
if (!table || table->name != q ||
!quarks[2] != table->leaf)
break;
}
}
pprev = prev;
quarks++;
bindings++;
}
if (!quarks[1]) {
q = *quarks;
entry = *(vprev = &LeafHash((LTable)table, q));
while (entry && entry->name != q)
entry = *(vprev = &entry->next);
if (entry && *bindings == XrmBindLoosely && entry->tight)
entry = *(vprev = &entry->next);
if (entry && entry->name == q &&
(*bindings == XrmBindTightly) == entry->tight) {
if ((type == XrmQString) == entry->string &&
entry->size == value->size) {
if (!entry->string)
RepType(entry) = type;
memcpy(RawValue(entry), (char *)value->addr, value->size);
return;
}
*vprev = entry->next;
Xfree((char *)entry);
(*pprev)->entries--;
}
prev = (NTable *)vprev;
}
}
firstpprev = pprev;
while (quarks[1]) {
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;
}
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;
}
entry->next = *((VEntry *)prev);
*((VEntry *)prev) = entry;
entry->size = value->size;
if (type == XrmQString) {
entry->string = 1;
} else {
entry->string = 0;
RepType(entry) = type;
}
memcpy(RawValue(entry), (char *)value->addr, value->size);
(*pprev)->entries++;
if (q > maxResourceQuark) {
unsigned oldsize = (maxResourceQuark + 1) >> 3;
unsigned size = ((q | 0x7f) + 1) >> 3;
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);
}
#define QLIST_SIZE 100
#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];
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;
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;
do {
bits = next_char(c, str);
} while is_space(bits);
if (is_EOL(bits))
continue;
if (c == '!') {
while (is_simple(bits = next_char(c, str))) {}
if (is_EOL(bits))
continue;
while (!is_EOL(bits = next_mbchar(c, len, str))) {}
str--;
continue;
}
if (c == '#') {
only_pcs = True;
while (is_space(bits = next_char(c, str))) {};
if (!strncmp(str, "include", 7)) {
str += (7-1);
while (is_space(bits = next_char(c, str))) {};
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));
if (c == '"')
GetIncludeFile(db, filename, fname, str - len - fname);
}
}
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;
}
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;
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;
do {
*ptr++ = c;
sig = (sig << 1) + c;
} while (is_space(bits = next_char(c, str)));
if (is_separator(bits))
break;
num_quarks--;
continue;
}
if (c == '.')
*(++t_bindings) = XrmBindTightly;
else
*(++t_bindings) = XrmBindLoosely;
sig = 0;
ptr = lhs;
}
else {
if (c == '*')
*t_bindings = XrmBindLoosely;
}
bits = next_char(c, str);
}
quarks[num_quarks] = NULLQUARK;
if (c != ':') {
char oldc;
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;
}
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;
}
ptr = rhs;
ptr_max = ptr + alloc_chars - 4;
only_pcs = True;
len = 1;
for(;;) {
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 == '\\') {
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') {
*ptr++ = '\n';
} else if (c == '\\') {
*ptr++ = '\\';
} else {
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 (count == 3) {
*ptr++ = (unsigned char) ((temp[0] - '0') * 0100 +
(temp[1] - '0') * 010 +
(temp[2] - '0'));
}
else {
int tcount;
for (tcount = 0; tcount < count; tcount++) {
*ptr++ = temp[tcount];
}
}
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);
}
}
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);
rhs = temp_str;
ptr_max = rhs + alloc_chars - 4;
}
}
*ptr++ = '\0';
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;
}
static char *
ReadInFile(_Xconst char *filename)
{
register int fd, size;
char * filebuf;
#ifdef __UNIXOS2__
filename = __XOS2RedirRoot(filename);
#endif
if ( (fd = _XOpenFile (filename, O_RDONLY)) == -1 )
return (char *)NULL;
GetSizeOfFile(fd, size);
if (!(filebuf = Xmalloc(size + 1))) {
close(fd);
return (char *)NULL;
}
size = read (fd, filebuf, size);
#ifdef __UNIXOS2__
{
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';
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;
}
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;
}
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;
#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; \
} \
}
#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;
leaf = 0;
bilevel = !names[1];
} else {
get = (getNTableEProcp)EnumLTable;
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);
ITIGHTLOOSE(*classes);
if (table->hasany) {
ITIGHTLOOSE(XrmQANY);
}
if (table->hasloose) {
while (1) {
names++;
classes++;
if (!*names)
break;
if (!names[1] && closure->mode != XrmEnumAllLevels) {
get = (getNTableEProcp)EnumLTable;
leaf = 1;
}
ILOOSE(*names);
ILOOSE(*classes);
if (table->hasany) {
ILOOSE(XrmQANY);
}
}
names--;
classes--;
}
}
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;
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
}
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);
}
}
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);
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
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);
}
#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; \
} \
}
#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; \
} \
}
static Bool AppendLEntry(
LTable table,
XrmNameList names,
XrmClassList classes,
register SClosure closure)
{
if (closure->idx >= 0 && closure->list[closure->idx] == table)
return False;
if (closure->idx == closure->limit)
return True;
closure->idx++;
closure->list[closure->idx] = table;
return False;
}
static Bool AppendLooseLEntry(
LTable table,
XrmNameList names,
XrmClassList classes,
register SClosure closure)
{
if (closure->idx >= 0 && closure->list[closure->idx] == table)
return False;
if (closure->idx >= closure->limit - 1)
return True;
closure->idx++;
closure->list[closure->idx] = LOOSESEARCH;
closure->idx++;
closure->list[closure->idx] = table;
return False;
}
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;
leaf = 0;
} else {
get = (getNTableSProcp)AppendLEntry;
leaf = 1;
}
GTIGHTLOOSE(*names, AppendLooseLEntry);
GTIGHTLOOSE(*classes, AppendLooseLEntry);
if (table->hasany) {
GTIGHTLOOSE(XrmQANY, AppendLooseLEntry);
}
if (table->hasloose) {
while (1) {
names++;
classes++;
if (!*names)
break;
if (!names[1]) {
get = (getNTableSProcp)AppendLEntry;
leaf = 1;
}
GLOOSE(*names, AppendLooseLEntry);
GLOOSE(*classes, AppendLooseLEntry);
if (table->hasany) {
GLOOSE(XrmQANY, AppendLooseLEntry);
}
}
}
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;
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,
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,
XrmValue *pValue)
{
register LTable *list;
register LTable table;
register VEntry entry = NULL;
int flags;
#define VTIGHTLOOSE(q) \
entry = LeafHash(table, q); \
while (entry && entry->name != q) \
entry = entry->next; \
if (entry) \
break
#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;
flags = 0;
if (IsResourceQuark(name))
flags = 2;
if (IsResourceQuark(class))
flags |= 1;
if (!flags) {
table = (LTable)NULL;
} else if (flags == 3) {
while ((table = *list++)) {
if (table != LOOSESEARCH) {
VTIGHTLOOSE(name);
VTIGHTLOOSE(class);
} else {
table = *list++;
VLOOSE(name);
VLOOSE(class);
}
}
} else {
if (flags == 1)
name = class;
while ((table = *list++)) {
if (table != LOOSESEARCH) {
VTIGHTLOOSE(name);
} else {
table = *list++;
VLOOSE(name);
}
}
}
if (table) {
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
}
static Bool GetVEntry(
LTable table,
XrmNameList names,
XrmClassList classes,
VClosure closure)
{
register VEntry entry;
register XrmQuark q;
q = *names;
entry = LeafHash(table, q);
while (entry && entry->name != q)
entry = entry->next;
if (!entry) {
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;
}
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;
while (names[1]) {
names++;
classes++;
}
VLOOSE(*names);
if (!entry) {
VLOOSE(*classes);
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
}
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;
leaf = 0;
} else {
get = (getNTableVProcp)GetVEntry;
leaf = 1;
}
GTIGHTLOOSE(*names, GetLooseVEntry);
GTIGHTLOOSE(*classes, GetLooseVEntry);
if (table->hasany) {
GTIGHTLOOSE(XrmQANY, GetLooseVEntry);
}
if (table->hasloose) {
while (1) {
names++;
classes++;
if (!names[1])
break;
if (!names[2]) {
get = (getNTableVProcp)GetVEntry;
leaf = 1;
}
GLOOSE(*names, GetLooseVEntry);
GLOOSE(*classes, GetLooseVEntry);
if (table->hasany) {
GLOOSE(XrmQANY, GetLooseVEntry);
}
}
}
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;
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,
XrmValuePtr pValue)
{
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(db, name_str, class_str, pType_str, pValue)
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;
}
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((char *)entry);
}
}
Xfree((char *)table->buckets);
Xfree((char *)table);
}
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((char *)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);
}
_XFreeMutex(&db->linfo);
(*db->methods->destroy)(db->mbstate);
Xfree((char *)db);
}
}