|
|
1.1 root 1: #include <X/mit-copyright.h>
2:
3: /* $Header: XGetDefault.c,v 10.7 86/12/01 14:50:34 jg Rel $ */
4: /* Copyright (c) 1985, Massachusetts Institute of Technology */
5:
6: /*
7: * This routine returns options out of the X user preferences file
8: * found in XDEFAULT, possibly modified by the .Xdefaults in the user's home
9: * directory. It either returns a pointer to
10: * the option or returns NULL if option not set. It is patterned after
11: * Andrew's file format (why be different for the sake of being different?).
12: * Andrew's code was NOT examined before writing this routine.
13: * It parses lines of the format "progname.option:value" and returns a pointer
14: * to value.
15: */
16:
17: #include <stdio.h>
18: #include <strings.h>
19: #include <ctype.h>
20: #include "Xdefault.h"
21:
22: #define XOPTIONFILE "/.Xdefaults" /* name in home directory of options
23: file. */
24: extern char *malloc();
25:
26: static struct ent {
27: struct ent *left; /* next option to left */
28: struct ent *right; /* next option to right */
29: char *oname; /* option name */
30: char *value; /* value for that option */
31: char bal; /* for avl use */
32: } *head;
33:
34: char *XGetDefault(prog, name)
35: register char *name; /* name of option program wants */
36: char *prog; /* name of program for option */
37: { /* to get, for example, "font" */
38: static nent = -1; /* have we been here before? */
39: register struct ent *cur; /* current entry being examined */
40: register int cmp;
41: char namebuf[64];
42: register char *pv = namebuf;
43:
44: strncpy(namebuf, name, sizeof(namebuf));
45: while (*pv) { /* convert upper to lower */
46: if (isupper(*pv)) *pv += 040;
47: pv++;
48: }
49: if (nent == -1)
50: nent = ReadFile(prog);/* if not, parse the file.*/
51: if (nent == 0)
52: return(NULL);
53: cur = head;
54: do {
55: if ((cmp = strcmp(namebuf, cur->oname)) == 0)
56: return(cur->value);
57: cur = cmp > 0 ? cur->right : cur->left;
58: } while (cur != NULL);
59: return(NULL); /* if no match, let him know */
60: }
61:
62: static ReadFile(prog)
63: char *prog; /* program name to match */
64: {
65: register char *point,*colon; /* where in the line the keys are */
66: register char *oname, *val; /* new memory for valid option line */
67: register FILE *fptr = NULL; /* preferences file */
68: register char *pv; /* pointer to value for lowering */
69: register int len;
70: register int nentries = 0; /* number of entries found */
71: register int first;
72: char fname[BUFSIZ]; /* longer than any conceivable size */
73: char line[BUFSIZ]; /* line buffer for each line of file*/
74: char *getenv();
75: char *home = getenv("HOME");
76:
77: if ((pv = rindex(prog,'/')) != NULL)
78: prog = pv + 1; /* if full path, get last component */
79: for(first = 1 ; first >= 0 ; first--) {
80: if(first) /* Use any defaults in XDEFAULTS. */
81: fptr = fopen(XDEFAULTS, "r");
82: else if (home != NULL) { /* try home directory */
83: strcpy(fname, home); /* form full path name of file */
84: strcat(fname, XOPTIONFILE);
85: fptr = fopen(fname, "r");
86: } else
87: break;
88: if(fptr == NULL)
89: continue;
90: while ( fgets(line, sizeof(line), fptr) != NULL ) {
91: if (line[0] == '#') continue; /* comment? */
92: point = index(line,'.');
93: colon = index(line,':');
94: if ( (point == NULL) || (colon == NULL) || (colon < point) )
95: continue; /* both . and : required on line*/
96: *point = 0;
97: if ( point != line ) /* check all chars up to '.' */
98: if (strcmp(line, prog) != 0)
99: continue;
100:
101: /*
102: * ok, we've passed all the tests, so it is a valid option for
103: * this program, or is global option.
104: */
105:
106: len = strlen(colon);
107: if(colon[len-1] == '\n')
108: colon[len-1] = '\0'; /* braindamaged fgets call */
109: /*
110: * allocate space for text
111: */
112: point++;
113: len = colon - point;
114: for(colon++ ; isspace(*colon) ; colon++); /* skip over spaces */
115: if((oname = malloc(len + strlen(colon) + 2)) == NULL) {
116: fprintf(stderr, "ReadFile: Out of memory\n");
117: exit(1);
118: }
119: strncpy(oname, point, len);
120: oname[len] = 0;
121: pv = oname;
122: while (*pv) { /* convert upper to lower */
123: if (isupper(*pv))
124: *pv += 040;
125: pv++;
126: }
127: val = oname + len + 1;
128: strcpy(val, colon);
129: insert(oname, val, &head);
130: nentries++;
131: }
132: fclose(fptr);
133: }
134: return(nentries);
135: }
136:
137: /*
138: * Modified from "Algorithms + Data Structures = Programs", Niklaus Wirth,
139: * 1976, section 4.4.7 Balanced Tree Insertion, page 220-221.
140: */
141: #define L_EQUILIBRATED 2
142: #define LEFTSLANTED 1
143: #define L_REBALANCE 0
144:
145: #define R_EQUILIBRATED 0
146: #define RIGHTSLANTED 1
147: #define R_REBALANCE 2
148:
149: static insert(name, val, ent)
150: register char *name, *val;
151: register struct ent **ent;
152: {
153: register struct ent *ent1, *ent2;
154: register int cmp;
155: char *calloc();
156:
157: if(*ent == NULL) { /* not in tree, insert it */
158: if((*ent = (struct ent *)calloc(1, sizeof(struct ent))) ==
159: NULL) {
160: fprintf(stderr, "insert: Out of memory\n");
161: exit(1);
162: }
163: (*ent)->oname = name;
164: (*ent)->value = val;
165: (*ent)->bal = LEFTSLANTED;
166: return(1);
167: }
168: if((cmp = strcmp(name, (*ent)->oname)) == 0) { /* match */
169: free((*ent)->oname);
170: (*ent)->oname = name;
171: (*ent)->value = val;
172: return(0);
173: }
174: if(cmp < 0) {
175: if(!insert(name, val, &(*ent)->left))
176: return(0);
177: /* left branch has grown higher */
178: switch((*ent)->bal) {
179: case L_EQUILIBRATED:
180: (*ent)->bal = LEFTSLANTED;
181: return(0);
182: case LEFTSLANTED:
183: (*ent)->bal = L_REBALANCE;
184: return(1);
185: case L_REBALANCE: /* rebalance */
186: if((ent1 = (*ent)->left)->bal == L_REBALANCE) {
187: /* single LL rotation */
188: (*ent)->left = ent1->right;
189: ent1->right = *ent;
190: (*ent)->bal = LEFTSLANTED;
191: *ent = ent1;
192: } else {
193: /* double LR rotation */
194: ent2 = ent1->right;
195: ent1->right = ent2->left;
196: ent2->left = ent1;
197: (*ent)->left = ent2->right;
198: ent2->right = *ent;
199: (*ent)->bal = (ent2->bal == L_REBALANCE) ?
200: L_EQUILIBRATED : LEFTSLANTED;
201: ent1->bal = (ent2->bal == L_EQUILIBRATED) ?
202: L_REBALANCE : LEFTSLANTED;
203: *ent = ent2;
204: }
205: (*ent)->bal = LEFTSLANTED;
206: return(0);
207: }
208: }
209: if(!insert(name, val, &(*ent)->right))
210: return(0);
211: /* right branch has grown higher */
212: switch((*ent)->bal) {
213: case R_EQUILIBRATED:
214: (*ent)->bal = RIGHTSLANTED;
215: return(0);
216: case RIGHTSLANTED:
217: (*ent)->bal = R_REBALANCE;
218: return(1);
219: case R_REBALANCE: /* rebalance */
220: if((ent1 = (*ent)->right)->bal == R_REBALANCE) {
221: /* single RR rotation */
222: (*ent)->right = ent1->left;
223: ent1->left = *ent;
224: (*ent)->bal = RIGHTSLANTED;
225: *ent = ent1;
226: } else {
227: /* double RL rotation */
228: ent2 = ent1->left;
229: ent1->left = ent2->right;
230: ent2->right = ent1;
231: (*ent)->right = ent2->left;
232: ent2->left = *ent;
233: (*ent)->bal = (ent2->bal == R_REBALANCE) ?
234: R_EQUILIBRATED : RIGHTSLANTED;
235: ent1->bal = (ent2->bal == R_EQUILIBRATED) ?
236: R_REBALANCE : RIGHTSLANTED;
237: *ent = ent2;
238: }
239: (*ent)->bal = RIGHTSLANTED;
240: return(0);
241: }
242: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.