|
|
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.