File:  [Research Unix] / researchv9 / X11 / src / X.V11R1 / lib / Xtk / Xrm.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:22:00 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv9-SUN3_old, researchv9-SUN3, HEAD
researchv9-SUN3(old)

#ifndef lint
static char rcsid[] = "$Header: /var/lib/cvsd/repos/research/researchv9/X11/src/X.V11R1/lib/Xtk/Xrm.c,v 1.1.1.1 2018/04/24 17:22:00 root Exp $";
#endif lint

/*
 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 * 
 *                         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 of Digital Equipment
 * Corporation 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.
 */
#include	"Xlib.h"
#include	"Xlibos.h"
#include	"Xresource.h"
#include	"XrmConvert.h"
#include	"Quarks.h"
#include	<stdio.h>
#include	<ctype.h>

extern void bcopy();

typedef	void (*DBEnumProc)();

#define HASHSIZE	64
#define HASHMASK	63
#define HashIndex(quark)	(quark & HASHMASK)

/*
typedef struct _XrmHashBucketRec	*XrmHashBucket;
*/
typedef struct _XrmHashBucketRec {
    XrmHashBucket		next;
    XrmQuark		quark;
    XrmResourceDataBase	db;
} XrmHashBucketRec;

/*
typedef XrmHashBucket	*XrmHashTable;
*/

/*
typedef XrmHashTable XrmSearchList[];
*/

typedef struct _XrmResourceDataBase {
    XrmRepresentation	type;
    XrmValue		val;
    XrmHashBucket	*hashTable;
    } XrmResourceDataBaseRec;


static XrmResourceDataBase rdb = NULL;

static Bool FindName(quark, hashTable, ppBucket)
    register	XrmQuark		quark;
    		XrmHashTable	hashTable;
    		XrmHashBucket	**ppBucket;
{
/*  search hashTable (which must be non-NULL) for quark.
    If found, *ppBucket is the address of the XrmHashBucket that points to it.
    If not,   *ppBucket is the address of the hashTable entry that should 
    	      point to a new XrmHashBucket; **ppBucket is the XrmHashBucket it 
	      should point to.
*/

    register XrmHashBucket *pBucket, *pStartBucket;
    
    pBucket = pStartBucket = &hashTable[HashIndex(quark)];

    while ((*pBucket) != NULL) {
	if ((*pBucket)->quark == quark) {
	    *ppBucket = pBucket;
	    return True;
	}
	pBucket = &((*pBucket)->next);
    }
    *ppBucket = pStartBucket;
    return False;
}


static void SetValue(type, val, pdb)
    XrmRepresentation	type;
    XrmValue		val;
    XrmResourceDataBase	*pdb;
{
    register	XrmResourceDataBase db = *pdb;

   if (db == NULL) {
	*pdb = db = (XrmResourceDataBase) Xmalloc (sizeof(XrmResourceDataBaseRec));
	db->type = NULLQUARK;
	db->val.addr = NULL;
	db->val.size = 0;
	db->hashTable = NULL;
    }

    db->type = type;
    if (db->val.addr != NULL)
        Xfree((char *)db->val.addr);
    db->val.addr = (caddr_t) Xmalloc(val.size);
    bcopy((char *)val.addr, (char *)db->val.addr, (int) val.size);
    db->val.size = val.size;
}

static void MakeNewDb(quarks, type, val, pdb)
    register XrmQuarkList	quarks;
	     XrmRepresentation	type;
    	     XrmValue		val;
    	     XrmResourceDataBase *pdb;
{
    register 	XrmResourceDataBase db;
    register	XrmHashBucket       *pBucket, bucket;

    /* make a new database tree rooted at *pdb, initialized with quark/val */
    /* quarks[0] can be NULLQUARK, in which case just set the value */

    for (; *quarks != NULLQUARK; quarks++) {
	db = *pdb = (XrmResourceDataBase) Xmalloc(sizeof(XrmResourceDataBaseRec));
	db->type = NULLQUARK;
	db->val.size = 0;
	db->val.addr = NULL;
	db->hashTable = (XrmHashTable) Xmalloc(sizeof(XrmHashBucket) * HASHSIZE);
	bzero((char *) db->hashTable, sizeof(XrmHashBucket) * HASHSIZE);
	pBucket = &(db->hashTable[HashIndex(*quarks)]);
	*pBucket = bucket = (XrmHashBucket) Xmalloc(sizeof(XrmHashBucketRec));
	bucket->next = NULL;
	bucket->quark = *quarks;
	bucket->db = NULL;
	pdb = &(bucket->db);
    }

    SetValue(type, val, pdb);
}

static void AddNameToLevel(quarks, pBucket, type, val)
    XrmQuarkList		quarks;
    XrmHashBucket		*pBucket;
    XrmRepresentation	type;
    XrmValue		val;
{
    /* add a new bucket to this level at pBucket */

    register XrmHashBucket bucket;

    /* Prepend new bucket to front of list */
    bucket = (XrmHashBucket) Xmalloc(sizeof(XrmHashBucketRec));
    bucket->next = *pBucket;
    *pBucket = bucket;
    bucket->quark = *quarks;
    bucket->db = NULL;

    MakeNewDb(&quarks[1], type, val, &(bucket->db));

}

static void PutEntry(quarks, type, val, db)
    register XrmQuarkList	quarks;
	     XrmRepresentation	type;
    	     XrmValue		val;
    register XrmResourceDataBase	*db;
{
    XrmHashBucket *pBucket;

    for (; *quarks != NULLQUARK; quarks++) {
	if (*db == NULL) {
	    MakeNewDb(quarks, type, val, db);
	    return;
	}
	if (! FindName(*quarks, (*db)->hashTable, &pBucket)) {
	    AddNameToLevel(quarks, pBucket, type, val);
	    return;
	    }
	db = &((*pBucket)->db);
	}

    /* update value for entry i */
    SetValue(type, val, db);

}

static Bool GetEntry(names, classes, type, val, hashTable)
    register XrmNameList        names;
    register XrmClassList       classes;
    	     XrmRepresentation  *type;
    	     XrmValue	       *val;
    register XrmHashTable         hashTable;
{
    register XrmHashBucket	 bucket;
    register XrmHashTable	 nextHashTable;

    for (; *names != NULLQUARK; names++, classes++) {
    	bucket = hashTable[HashIndex(*names)];
	while (bucket != NULL) {
	    if (bucket->quark == *names) {
	    	if (names[1] == NULLQUARK) {
		    *val = bucket->db->val;
		    /* Must be leaf node with data, else doesn't really match */
		    if ((*val).addr) {
			*type = bucket->db->type;
		    	return True;
		    } else
			return False;
	    	} else if ((nextHashTable = bucket->db->hashTable)
		 && GetEntry(names+1, classes+1, type, val, nextHashTable)) {
	    	    return True;
	    	} else {
		    break;
		}
	    }
	    bucket = bucket->next;
    	}
    	bucket = hashTable[HashIndex(*classes)];
	while (bucket != NULL) {
	    if (bucket->quark == *classes) {
	    	if (classes[1] == NULLQUARK) {
		    *val = bucket->db->val;
		    /* Must be leaf node with data, else doesn't really match */
		    if ((*val).addr) {
			*type = bucket->db->type;
		    	return True;
		    } else
			return False;
	    	} else if ((nextHashTable = bucket->db->hashTable)
		 && GetEntry(names+1, classes+1, type, val, nextHashTable)) {
	    	    return True;
	    	} else {
		    break;
		}
	    }
	    bucket = bucket->next;
    	}
    }
    return False;
}


static int searchListCount;

static void GetSearchList(names, classes, searchList, hashTable)
    register XrmNameList  names;
    register XrmClassList classes;
    XrmSearchList		 searchList;
    register XrmHashTable	 hashTable;
{
    register XrmHashBucket	 bucket;
    register XrmHashTable	 nextHashTable;

    for (; *names != NULLQUARK; names++, classes++) {
    	bucket = hashTable[HashIndex(*names)];
	while (bucket != NULL) {
	    if (bucket->quark == *names) {
		nextHashTable = bucket->db->hashTable;
	    	if (nextHashTable) {
		    if (names[1] != NULLQUARK)
			GetSearchList(names+1,classes+1, 
			 searchList,nextHashTable);
		    searchList[searchListCount++] = nextHashTable;
		}
		break;
	    }
	    bucket = bucket->next;
    	}
    	bucket = hashTable[HashIndex(*classes)];
	while (bucket != NULL) {
	    if (bucket->quark == *classes) {
		nextHashTable = bucket->db->hashTable;
	    	if (nextHashTable) {
		    if (classes[1] != NULLQUARK)
			GetSearchList(names+1,classes+1,
			 searchList,nextHashTable);
		    searchList[searchListCount++] = nextHashTable;
		}
		break;
	    }
	    bucket = bucket->next;
    	}
    }
}

void XrmGetSearchList(names, classes, searchList)
    XrmNameList  names;
    XrmClassList classes;
    XrmSearchList	searchList;	/* RETURN */
{
    searchListCount = 0;
    if (rdb && rdb->hashTable) {
        GetSearchList(names, classes, searchList, rdb->hashTable);
        searchList[searchListCount++] = rdb->hashTable;
    }
    searchList[searchListCount] = NULL;
}

void XrmGetSearchResource(dpy, searchList, name, class, type, pVal)
	     Display	*dpy;
    register XrmSearchList	searchList;
    register XrmName	name;
    register XrmClass	class;
    	     XrmRepresentation	type;
    	     XrmValue	*pVal;	/* RETURN */
{
    register XrmHashBucket	bucket;
    register int	nameHash = HashIndex(name);
    register int	classHash = HashIndex(class);

    for (; (*searchList) != NULL; searchList++) {
	bucket = (*searchList)[nameHash];
	while (bucket != NULL) {
	    if (bucket->quark == name) {
		if (bucket->db->val.addr != NULL) {
		    /* Leaf node, it really matches */
		    _XrmConvert(dpy, bucket->db->type, bucket->db->val,
		    	 type, pVal);
		    return;
		}
		break;
	    }
	    bucket = bucket->next;
    	}
	bucket = (*searchList)[classHash];
	while (bucket != NULL) {
	    if (bucket->quark == class) {
		if (bucket->db->val.addr != NULL) {
		    /* Leaf node, it really matches */
		    _XrmConvert(dpy, bucket->db->type, bucket->db->val,
		               type, pVal);
		    return;
		}
		break;
	    }
	    bucket = bucket->next;
    	}
    }
    (*pVal).addr = NULL;
    (*pVal).size = 0;
}


void XrmPutResource(quarks, type, value)
    XrmQuarkList		quarks;
    XrmRepresentation	type;
    XrmValue		value;
{
    PutEntry(quarks, type, value, &rdb);
}

void XrmSetCurrentDataBase(db)
    XrmResourceDataBase	db;
{
    rdb = db;
}

void XrmGetCurrentDataBase(db)
    XrmResourceDataBase	*db;
{
    if (db != NULL)
	*db = rdb;
}

void XrmGetDataBase(magicCookie, db)
    FILE		*magicCookie;
    XrmResourceDataBase	*db;
{
    char		buf[1000], *s, *valStr;
    XrmQuark		nl[100];
    int			i;
    XrmResourceDataBase	odb = rdb;
    XrmValue		val;

    *db = NULL;
    if (magicCookie == NULL)
    	return;

    rdb = NULL;
    for (;;) {
	s = fgets(buf, sizeof(buf), magicCookie);
	if (s == NULL) break;
	for (; isspace(s[0]); s++) ;
	if ((s[0] == '\0') || (s[0] == '#')) continue;
	i = strlen(s);
	if (s[i-1] == '\n') s[i-1] = '\0';
	for (i=0 ; ; i++) {
	    if (s[i] == '\0') {
		valStr = "";
		break;
	    }
	    if ((s[i] == ':') || isspace(s[i])) {
		valStr = &s[i+1];
		for (; isspace(valStr[0]); valStr++) ;
		s[i] = '\0';
		break;
	    }
	}
	XrmStringToQuarkList(s, nl);
	val.size = strlen(valStr)+1;
	val.addr = (caddr_t) valStr;
	XrmPutResource(&nl[0], XrmQString, val);
    }
    *db = rdb;
    rdb = odb;
}

static void Enum(quarks, count, db, cd, proc)
    XrmQuarkList	quarks;
    unsigned	count;
    XrmResourceDataBase db;
    unspecified cd;
    DBEnumProc  proc;
{
    unsigned int	i;
    XrmHashBucket bucket;

    if (db == NULL) return;
    if (db->hashTable != NULL) {
	quarks[count+1] = NULLQUARK;
	for (i=0; i < HASHSIZE; i++) {
	    bucket = db->hashTable[i];
	    while (bucket != NULL) {
	    	quarks[count] = bucket->quark;
	    	Enum(quarks, count+1, bucket->db, cd, proc);
		bucket = bucket->next;
	    }
	}
    }
    quarks[count] = NULLQUARK;
    if (db->val.addr != NULL) proc(quarks, db->type, db->val, cd);
    }

static void EnumerateDataBase(db, cd, proc)
    XrmResourceDataBase	db;
    unspecified	cd;
    DBEnumProc	proc;
    {
    XrmQuark	nl[100];
    Enum(nl, 0, db, cd, proc);
}

void PrintQuark(quark)
    XrmQuark	quark;
{
    (void) printf("%s", XrmQuarkToAtom(quark));
}

void PrintQuarkList(quarks)
    XrmQuarkList	quarks;
{
    Bool	firstNameSeen;

    for (firstNameSeen = False; (*quarks) != NULLQUARK; quarks++) {
        if (firstNameSeen) (void) printf(".");
	firstNameSeen = True;
	PrintQuark(*quarks);
    }
}

static void DumpEntry(quarks, stream, type, val)
    XrmQuarkList	     quarks;
    XrmRepresentation type;
    XrmValue	     val;
    FILE	     *stream;
{

    register unsigned int	i;

    for (i=0; quarks[i] != NULLQUARK; i++) {
	if (i != 0) (void) fprintf(stream, ".");
	(void) fprintf(stream, "%s", XrmQuarkToAtom(*quarks));
    }
    if (type == XrmQString) {
	(void) fprintf(stream, ":\t%s\n", val.addr);
    } else {
	(void) fprintf(stream, "!%s:\t", XrmRepresentationToAtom(type));
	for (i = 0; i < val.size; i++)
	    (void) fprintf(stream, "%02x", (int) val.addr[i]);
        (void) fprintf(stream, "\n");
    }
}

void XrmPutDataBase(magicCookie, db)
    FILE		*magicCookie;
    XrmResourceDataBase	db;
{
    EnumerateDataBase(db, (unspecified) magicCookie, DumpEntry);
}

void XrmMergeDataBases(new, into)
    XrmResourceDataBase	new, *into;
{
    EnumerateDataBase(new, (unspecified) into, PutEntry);
}

void XrmGetResource(dpy, names, classes, destType, val)
    Display		*dpy;
    XrmNameList		names;
    XrmClassList 	classes;
    XrmRepresentation	destType;
    XrmValue		*val;
    {
    XrmRepresentation	fromType;
    XrmValue 		from;

    if (rdb && rdb->hashTable
     && GetEntry(names, classes, &fromType, &from, rdb->hashTable)) {
	_XrmConvert(dpy, fromType, from, destType, val);
    } else {
	(*val).addr = NULL;
	(*val).size = 0;
    }
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.