|
|
1.1 root 1: /* $Header: Xrm.c,v 1.1 87/09/12 12:27:21 toddb Exp $ */
2: /* $Header: Xrm.c,v 1.1 87/09/12 12:27:21 toddb Exp $ */
3: #ifndef lint
4: static char *sccsid = "@(#)Xrm.c 1.11 3/20/87";
5: #endif lint
6:
7: /*
8: * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
9: *
10: * All Rights Reserved
11: *
12: * Permission to use, copy, modify, and distribute this software and its
13: * documentation for any purpose and without fee is hereby granted,
14: * provided that the above copyright notice appear in all copies and that
15: * both that copyright notice and this permission notice appear in
16: * supporting documentation, and that the name of Digital Equipment
17: * Corporation not be used in advertising or publicity pertaining to
18: * distribution of the software without specific, written prior permission.
19: *
20: *
21: * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
22: * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
23: * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
24: * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
25: * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
26: * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
27: * SOFTWARE.
28: */
29:
30:
31: #include "Xlib.h"
32: #include "Xlibos.h"
33: #include "Xresource.h"
34: #include "XrmConvert.h"
35: #include "Quarks.h"
36: #include <stdio.h>
37: #include <ctype.h>
38:
39: extern void bcopy();
40:
41: typedef void (*DBEnumProc)();
42:
43: #define HASHSIZE 64
44: #define HASHMASK 63
45: #define HashIndex(quark) (quark & HASHMASK)
46:
47: /*
48: typedef struct _XrmHashBucketRec *XrmHashBucket;
49: */
50: typedef struct _XrmHashBucketRec {
51: XrmHashBucket next;
52: XrmQuark quark;
53: XrmResourceDataBase db;
54: } XrmHashBucketRec;
55:
56: /*
57: typedef XrmHashBucket *XrmHashTable;
58: */
59:
60: /*
61: typedef XrmHashTable XrmSearchList[];
62: */
63:
64: typedef struct _XrmResourceDataBase {
65: XrmRepresentation type;
66: XrmValue val;
67: XrmHashBucket *hashTable;
68: } XrmResourceDataBaseRec;
69:
70: static Bool FindName(quark, hashTable, ppBucket)
71: register XrmQuark quark;
72: XrmHashTable hashTable;
73: XrmHashBucket **ppBucket;
74: {
75: /* search hashTable (which must be non-NULL) for quark.
76: If found, *ppBucket is the address of the XrmHashBucket that points to it.
77: If not, *ppBucket is the address of the hashTable entry that should
78: point to a new XrmHashBucket; **ppBucket is the XrmHashBucket it
79: should point to.
80: */
81:
82: register XrmHashBucket *pBucket, *pStartBucket;
83:
84: pBucket = pStartBucket = &hashTable[HashIndex(quark)];
85:
86: while ((*pBucket) != NULL) {
87: if ((*pBucket)->quark == quark) {
88: *ppBucket = pBucket;
89: return True;
90: }
91: pBucket = &((*pBucket)->next);
92: }
93: *ppBucket = pStartBucket;
94: return False;
95: }
96:
97:
98: static void SetValue(pdb, type, val)
99: XrmResourceDataBase *pdb;
100: XrmRepresentation type;
101: XrmValuePtr val;
102: {
103: register XrmResourceDataBase db = *pdb;
104:
105: if (db == NULL) {
106: *pdb = db = (XrmResourceDataBase) Xmalloc (sizeof(XrmResourceDataBaseRec));
107: db->type = NULLQUARK;
108: db->val.addr = NULL;
109: db->val.size = 0;
110: db->hashTable = NULL;
111: }
112:
113: db->type = type;
114: if (db->val.addr != NULL)
115: Xfree((char *)db->val.addr);
116: db->val.addr = (caddr_t) Xmalloc(val->size);
117: bcopy((char *)val->addr, (char *)db->val.addr, (int) val->size);
118: db->val.size = val->size;
119: }
120:
121: static void MakeNewDb(pdb, quarks, type, val)
122: XrmResourceDataBase *pdb;
123: register XrmQuarkList quarks;
124: XrmRepresentation type;
125: XrmValuePtr val;
126: {
127: register XrmResourceDataBase db;
128: register XrmHashBucket *pBucket, bucket;
129:
130: /* make a new database tree rooted at *pdb, initialized with quark/val */
131: /* quarks[0] can be NULLQUARK, in which case just set the value */
132:
133: for (; *quarks != NULLQUARK; quarks++) {
134: db = *pdb = (XrmResourceDataBase) Xmalloc(sizeof(XrmResourceDataBaseRec));
135: db->type = NULLQUARK;
136: db->val.size = 0;
137: db->val.addr = NULL;
138: db->hashTable = (XrmHashTable) Xmalloc(sizeof(XrmHashBucket) * HASHSIZE);
139: bzero((char *) db->hashTable, sizeof(XrmHashBucket) * HASHSIZE);
140: pBucket = &(db->hashTable[HashIndex(*quarks)]);
141: *pBucket = bucket = (XrmHashBucket) Xmalloc(sizeof(XrmHashBucketRec));
142: bucket->next = NULL;
143: bucket->quark = *quarks;
144: bucket->db = NULL;
145: pdb = &(bucket->db);
146: }
147:
148: SetValue(pdb, type, val);
149: }
150:
151: static void AddNameToLevel(quarks, pBucket, type, val)
152: XrmQuarkList quarks;
153: XrmHashBucket *pBucket;
154: XrmRepresentation type;
155: XrmValuePtr val;
156: {
157: /* add a new bucket to this level at pBucket */
158:
159: register XrmHashBucket bucket;
160:
161: /* Prepend new bucket to front of list */
162: bucket = (XrmHashBucket) Xmalloc(sizeof(XrmHashBucketRec));
163: bucket->next = *pBucket;
164: *pBucket = bucket;
165: bucket->quark = *quarks;
166: bucket->db = NULL;
167:
168: MakeNewDb(&(bucket->db), &quarks[1], type, val);
169:
170: }
171:
172: static void PutEntry(db, quarks, type, val)
173: register XrmResourceDataBase *db;
174: register XrmQuarkList quarks;
175: XrmRepresentation type;
176: XrmValue val;
177: {
178: XrmHashBucket *pBucket;
179:
180: for (; *quarks != NULLQUARK; quarks++) {
181: if (*db == NULL) {
182: MakeNewDb(db, quarks, type, &val);
183: return;
184: }
185: if (! FindName(*quarks, (*db)->hashTable, &pBucket)) {
186: AddNameToLevel(quarks, pBucket, type, &val);
187: return;
188: }
189: db = &((*pBucket)->db);
190: }
191:
192: /* update value for entry i */
193: SetValue(db, type, &val);
194:
195: }
196:
197: static Bool GetEntry(names, classes, type, val, hashTable)
198: register XrmNameList names;
199: register XrmClassList classes;
200: XrmRepresentation *type;
201: XrmValuePtr val;
202: register XrmHashTable hashTable;
203: {
204: register XrmHashBucket bucket;
205: register XrmHashTable nextHashTable;
206:
207: for (; *names != NULLQUARK; names++, classes++) {
208: bucket = hashTable[HashIndex(*names)];
209: while (bucket != NULL) {
210: if (bucket->quark == *names) {
211: if (names[1] == NULLQUARK) {
212: *val = bucket->db->val;
213: /* Must be leaf node with data, else doesn't really match */
214: if ((*val).addr) {
215: *type = bucket->db->type;
216: return True;
217: } else
218: return False;
219: } else if ((nextHashTable = bucket->db->hashTable)
220: && GetEntry(names+1, classes+1, type, val, nextHashTable)) {
221: return True;
222: } else {
223: break;
224: }
225: }
226: bucket = bucket->next;
227: }
228: bucket = hashTable[HashIndex(*classes)];
229: while (bucket != NULL) {
230: if (bucket->quark == *classes) {
231: if (classes[1] == NULLQUARK) {
232: *val = bucket->db->val;
233: /* Must be leaf node with data, else doesn't really match */
234: if ((*val).addr) {
235: *type = bucket->db->type;
236: return True;
237: } else
238: return False;
239: } else if ((nextHashTable = bucket->db->hashTable)
240: && GetEntry(names+1, classes+1, type, val, nextHashTable)) {
241: return True;
242: } else {
243: break;
244: }
245: }
246: bucket = bucket->next;
247: }
248: }
249: return False;
250: }
251:
252:
253: static int searchListCount;
254:
255: static void GetSearchList(names, classes, searchList, hashTable)
256: register XrmNameList names;
257: register XrmClassList classes;
258: XrmSearchList searchList;
259: register XrmHashTable hashTable;
260: {
261: register XrmHashBucket bucket;
262: register XrmHashTable nextHashTable;
263:
264: for (; *names != NULLQUARK; names++, classes++) {
265: bucket = hashTable[HashIndex(*names)];
266: while (bucket != NULL) {
267: if (bucket->quark == *names) {
268: nextHashTable = bucket->db->hashTable;
269: if (nextHashTable) {
270: if (names[1] != NULLQUARK)
271: GetSearchList(names+1,classes+1,
272: searchList,nextHashTable);
273: searchList[searchListCount++] = nextHashTable;
274: }
275: break;
276: }
277: bucket = bucket->next;
278: }
279: bucket = hashTable[HashIndex(*classes)];
280: while (bucket != NULL) {
281: if (bucket->quark == *classes) {
282: nextHashTable = bucket->db->hashTable;
283: if (nextHashTable) {
284: if (classes[1] != NULLQUARK)
285: GetSearchList(names+1,classes+1,
286: searchList,nextHashTable);
287: searchList[searchListCount++] = nextHashTable;
288: }
289: break;
290: }
291: bucket = bucket->next;
292: }
293: }
294: }
295:
296: void XrmGetSearchList(rdb, names, classes, searchList)
297: XrmResourceDataBase rdb;
298: XrmNameList names;
299: XrmClassList classes;
300: XrmSearchList searchList; /* RETURN */
301: {
302: searchListCount = 0;
303: if (rdb && rdb->hashTable) {
304: GetSearchList(names, classes, searchList, rdb->hashTable);
305: searchList[searchListCount++] = rdb->hashTable;
306: }
307: searchList[searchListCount] = NULL;
308: }
309:
310: void XrmGetSearchResource(screen, searchList, name, class, type, pVal)
311: Screen *screen;
312: register XrmSearchList searchList;
313: register XrmName name;
314: register XrmClass class;
315: XrmAtom type;
316: XrmValuePtr pVal; /* RETURN */
317: {
318: register XrmHashBucket bucket;
319: register int nameHash = HashIndex(name);
320: register int classHash = HashIndex(class);
321:
322: for (; (*searchList) != NULL; searchList++) {
323: bucket = (*searchList)[nameHash];
324: while (bucket != NULL) {
325: if (bucket->quark == name) {
326: if (bucket->db->val.addr != NULL) {
327: /* Leaf node, it really matches */
328: _XrmConvert(screen, bucket->db->type, &bucket->db->val,
329: XrmAtomToRepresentation(type), pVal);
330: return;
331: }
332: break;
333: }
334: bucket = bucket->next;
335: }
336: bucket = (*searchList)[classHash];
337: while (bucket != NULL) {
338: if (bucket->quark == class) {
339: if (bucket->db->val.addr != NULL) {
340: /* Leaf node, it really matches */
341: _XrmConvert(screen, bucket->db->type, &bucket->db->val,
342: XrmAtomToRepresentation(type), pVal);
343: return;
344: }
345: break;
346: }
347: bucket = bucket->next;
348: }
349: }
350: (*pVal).addr = NULL;
351: (*pVal).size = 0;
352: }
353:
354: void XrmPutResource(rdb, quarks, type, value)
355: XrmResourceDataBase *rdb;
356: XrmQuarkList quarks;
357: XrmRepresentation type;
358: XrmValuePtr value;
359: {
360: PutEntry(rdb, quarks, type, *value);
361: }
362:
363: static char *getstring(buf, nchars, dp)
364: char *buf;
365: register int nchars;
366: char **dp;
367: {
368: register char *p = *dp;
369: register char c;
370: if (*p == '\0') return NULL;
371: while (--nchars > 0) {
372: *buf++ = c = *p++;
373: if (c == '\n' || c == '\0') {
374: *dp = p;
375: return (buf);
376: }
377: }
378: return buf;
379: }
380:
381: XrmResourceDataBase XrmLoadDataBase(data)
382: char *data;
383: {
384: char buf[1000];
385: register char *s, *valStr;
386: XrmQuark nl[100];
387: register int i;
388: XrmValue val;
389: char *dp = data;
390: XrmResourceDataBase db;
391:
392: if (data == NULL || data[0] == '\0')
393: return NULL;
394:
395: for (;;) {
396: s = getstring(buf, sizeof(buf), &dp);
397: if (s == NULL) break;
398: for (; isspace(s[0]); s++) ;
399: if ((s[0] == '\0') || (s[0] == '#')) continue;
400: i = strlen(s);
401: if (s[i-1] == '\n') s[i-1] = '\0';
402: for (i=0 ; ; i++) {
403: if (s[i] == '\0') {
404: valStr = "";
405: break;
406: }
407: if ((s[i] == ':') || isspace(s[i])) {
408: valStr = &s[i+1];
409: for (; isspace(valStr[0]); valStr++) ;
410: s[i] = '\0';
411: break;
412: }
413: }
414: XrmStringToQuarkList(s, nl);
415: val.size = strlen(valStr)+1;
416: val.addr = (caddr_t) valStr;
417: XrmPutResource(&db, &nl[0], XrmQString, &val);
418: }
419: return db;
420: }
421:
422: XrmResourceDataBase XrmGetDataBase(magicCookie)
423: char *magicCookie;
424: {
425: char buf[1000];
426: register char *s, *valStr;
427: XrmQuark nl[100];
428: register int i;
429: XrmValue val;
430: FILE *magicCookieFile;
431: XrmResourceDataBase db;
432:
433: if (magicCookie == NULL)
434: return NULL;
435:
436: if((magicCookieFile = fopen(magicCookie, "r")) == NULL){
437: return NULL;
438: }
439: for (;;) {
440: s = fgets(buf, sizeof(buf), magicCookieFile);
441: if (s == NULL) break;
442: for (; isspace(s[0]); s++) ;
443: if ((s[0] == '\0') || (s[0] == '#')) continue;
444: i = strlen(s);
445: if (s[i-1] == '\n') s[i-1] = '\0';
446: for (i=0 ; ; i++) {
447: if (s[i] == '\0') {
448: valStr = "";
449: break;
450: }
451: if ((s[i] == ':') || isspace(s[i])) {
452: valStr = &s[i+1];
453: for (; isspace(valStr[0]); valStr++) ;
454: s[i] = '\0';
455: break;
456: }
457: }
458: XrmStringToQuarkList(s, nl);
459: val.size = strlen(valStr)+1;
460: val.addr = (caddr_t) valStr;
461: XrmPutResource(&db, &nl[0], XrmQString, &val);
462: }
463: fclose(magicCookieFile);
464: return db;
465: }
466:
467: static void Enum(db, quarks, count, cd, proc)
468: XrmResourceDataBase db;
469: XrmQuarkList quarks;
470: unsigned count;
471: unspecified cd;
472: DBEnumProc proc;
473: {
474: unsigned int i;
475: XrmHashBucket bucket;
476:
477: if (db == NULL) return;
478: if (db->hashTable != NULL) {
479: quarks[count+1] = NULLQUARK;
480: for (i=0; i < HASHSIZE; i++) {
481: bucket = db->hashTable[i];
482: while (bucket != NULL) {
483: quarks[count] = bucket->quark;
484: Enum(bucket->db, quarks, count+1, cd, proc);
485: bucket = bucket->next;
486: }
487: }
488: }
489: quarks[count] = NULLQUARK;
490: if (db->val.addr != NULL) proc(cd, quarks, db->type, db->val);
491: }
492:
493: static void EnumerateDataBase(db, cd, proc)
494: XrmResourceDataBase db;
495: unspecified cd;
496: DBEnumProc proc;
497: {
498: XrmQuark nl[100];
499: Enum(db, nl, 0, cd, proc);
500: }
501:
502: void PrintQuark(quark)
503: XrmQuark quark;
504: {
505: (void) printf("%s", XrmQuarkToAtom(quark));
506: }
507:
508: void PrintQuarkList(quarks)
509: XrmQuarkList quarks;
510: {
511: Bool firstNameSeen;
512:
513: for (firstNameSeen = False; (*quarks) != NULLQUARK; quarks++) {
514: if (firstNameSeen) (void) printf(".");
515: firstNameSeen = True;
516: PrintQuark(*quarks);
517: }
518: }
519:
520: static void DumpEntry(quarks, type, val, stream)
521: XrmQuarkList quarks;
522: XrmRepresentation type;
523: XrmValue val;
524: FILE *stream;
525: {
526:
527: register unsigned int i;
528:
529: for (i=0; quarks[i] != NULLQUARK; i++) {
530: if (i != 0) (void) fprintf(stream, ".");
531: (void) fprintf(stream, "%s", XrmQuarkToAtom(*quarks));
532: }
533: if (type == XrmQString) {
534: (void) fprintf(stream, ":\t%s\n", val.addr);
535: } else {
536: (void) fprintf(stream, "!%s:\t", XrmRepresentationToAtom(type));
537: for (i = 0; i < val.size; i++)
538: (void) fprintf(stream, "%02x", (int) val.addr[i]);
539: (void) fprintf(stream, "\n");
540: }
541: }
542:
543: void XrmPutDataBase(db, magicCookie)
544: XrmResourceDataBase db;
545: char *magicCookie;
546: {
547: FILE *magicCookieFile;
548:
549: if((magicCookieFile = fopen(magicCookie, "w")) == NULL) return;
550: EnumerateDataBase(db, (unspecified) magicCookieFile, DumpEntry);
551: }
552:
553: void XrmMergeDataBases(new, into)
554: XrmResourceDataBase new, *into;
555: {
556: EnumerateDataBase(new, (unspecified) into, PutEntry);
557: }
558:
559: void XrmGetResource(screen, rdb, names, classes, destType, val)
560: Screen *screen;
561: XrmResourceDataBase rdb;
562: XrmNameList names;
563: XrmClassList classes;
564: XrmRepresentation destType;
565: XrmValuePtr val;
566: {
567: XrmRepresentation fromType;
568: XrmValue from;
569:
570: if (rdb && rdb->hashTable
571: && GetEntry(names, classes, &fromType, &from, rdb->hashTable)) {
572: _XrmConvert(screen, fromType, &from, destType, val);
573: } else {
574: (*val).addr = NULL;
575: (*val).size = 0;
576: }
577: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.