|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T X
Length: 6705 (0x1a31) Types: TextFile Names: »XGetDefault.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦526ad3590⟧ »EUUGD11/gnu-31mar87/X.V10.R4.tar.Z« └─⟦2109abc41⟧ └─⟦this⟧ »./X.V10R4/Xlib/XGetDefault.c«
#include <X/mit-copyright.h> /* $Header: XGetDefault.c,v 10.7 86/12/01 14:50:34 jg Rel $ */ /* Copyright (c) 1985, Massachusetts Institute of Technology */ /* * This routine returns options out of the X user preferences file * found in XDEFAULT, possibly modified by the .Xdefaults in the user's home * directory. It either returns a pointer to * the option or returns NULL if option not set. It is patterned after * Andrew's file format (why be different for the sake of being different?). * Andrew's code was NOT examined before writing this routine. * It parses lines of the format "progname.option:value" and returns a pointer * to value. */ #include <stdio.h> #include <strings.h> #include <ctype.h> #include "Xdefault.h" #define XOPTIONFILE "/.Xdefaults" /* name in home directory of options file. */ extern char *malloc(); static struct ent { struct ent *left; /* next option to left */ struct ent *right; /* next option to right */ char *oname; /* option name */ char *value; /* value for that option */ char bal; /* for avl use */ } *head; char *XGetDefault(prog, name) register char *name; /* name of option program wants */ char *prog; /* name of program for option */ { /* to get, for example, "font" */ static nent = -1; /* have we been here before? */ register struct ent *cur; /* current entry being examined */ register int cmp; char namebuf[64]; register char *pv = namebuf; strncpy(namebuf, name, sizeof(namebuf)); while (*pv) { /* convert upper to lower */ if (isupper(*pv)) *pv += 040; pv++; } if (nent == -1) nent = ReadFile(prog);/* if not, parse the file.*/ if (nent == 0) return(NULL); cur = head; do { if ((cmp = strcmp(namebuf, cur->oname)) == 0) return(cur->value); cur = cmp > 0 ? cur->right : cur->left; } while (cur != NULL); return(NULL); /* if no match, let him know */ } static ReadFile(prog) char *prog; /* program name to match */ { register char *point,*colon; /* where in the line the keys are */ register char *oname, *val; /* new memory for valid option line */ register FILE *fptr = NULL; /* preferences file */ register char *pv; /* pointer to value for lowering */ register int len; register int nentries = 0; /* number of entries found */ register int first; char fname[BUFSIZ]; /* longer than any conceivable size */ char line[BUFSIZ]; /* line buffer for each line of file*/ char *getenv(); char *home = getenv("HOME"); if ((pv = rindex(prog,'/')) != NULL) prog = pv + 1; /* if full path, get last component */ for(first = 1 ; first >= 0 ; first--) { if(first) /* Use any defaults in XDEFAULTS. */ fptr = fopen(XDEFAULTS, "r"); else if (home != NULL) { /* try home directory */ strcpy(fname, home); /* form full path name of file */ strcat(fname, XOPTIONFILE); fptr = fopen(fname, "r"); } else break; if(fptr == NULL) continue; while ( fgets(line, sizeof(line), fptr) != NULL ) { if (line[0] == '#') continue; /* comment? */ point = index(line,'.'); colon = index(line,':'); if ( (point == NULL) || (colon == NULL) || (colon < point) ) continue; /* both . and : required on line*/ *point = 0; if ( point != line ) /* check all chars up to '.' */ if (strcmp(line, prog) != 0) continue; /* * ok, we've passed all the tests, so it is a valid option for * this program, or is global option. */ len = strlen(colon); if(colon[len-1] == '\n') colon[len-1] = '\0'; /* braindamaged fgets call */ /* * allocate space for text */ point++; len = colon - point; for(colon++ ; isspace(*colon) ; colon++); /* skip over spaces */ if((oname = malloc(len + strlen(colon) + 2)) == NULL) { fprintf(stderr, "ReadFile: Out of memory\n"); exit(1); } strncpy(oname, point, len); oname[len] = 0; pv = oname; while (*pv) { /* convert upper to lower */ if (isupper(*pv)) *pv += 040; pv++; } val = oname + len + 1; strcpy(val, colon); insert(oname, val, &head); nentries++; } fclose(fptr); } return(nentries); } /* * Modified from "Algorithms + Data Structures = Programs", Niklaus Wirth, * 1976, section 4.4.7 Balanced Tree Insertion, page 220-221. */ #define L_EQUILIBRATED 2 #define LEFTSLANTED 1 #define L_REBALANCE 0 #define R_EQUILIBRATED 0 #define RIGHTSLANTED 1 #define R_REBALANCE 2 static insert(name, val, ent) register char *name, *val; register struct ent **ent; { register struct ent *ent1, *ent2; register int cmp; char *calloc(); if(*ent == NULL) { /* not in tree, insert it */ if((*ent = (struct ent *)calloc(1, sizeof(struct ent))) == NULL) { fprintf(stderr, "insert: Out of memory\n"); exit(1); } (*ent)->oname = name; (*ent)->value = val; (*ent)->bal = LEFTSLANTED; return(1); } if((cmp = strcmp(name, (*ent)->oname)) == 0) { /* match */ free((*ent)->oname); (*ent)->oname = name; (*ent)->value = val; return(0); } if(cmp < 0) { if(!insert(name, val, &(*ent)->left)) return(0); /* left branch has grown higher */ switch((*ent)->bal) { case L_EQUILIBRATED: (*ent)->bal = LEFTSLANTED; return(0); case LEFTSLANTED: (*ent)->bal = L_REBALANCE; return(1); case L_REBALANCE: /* rebalance */ if((ent1 = (*ent)->left)->bal == L_REBALANCE) { /* single LL rotation */ (*ent)->left = ent1->right; ent1->right = *ent; (*ent)->bal = LEFTSLANTED; *ent = ent1; } else { /* double LR rotation */ ent2 = ent1->right; ent1->right = ent2->left; ent2->left = ent1; (*ent)->left = ent2->right; ent2->right = *ent; (*ent)->bal = (ent2->bal == L_REBALANCE) ? L_EQUILIBRATED : LEFTSLANTED; ent1->bal = (ent2->bal == L_EQUILIBRATED) ? L_REBALANCE : LEFTSLANTED; *ent = ent2; } (*ent)->bal = LEFTSLANTED; return(0); } } if(!insert(name, val, &(*ent)->right)) return(0); /* right branch has grown higher */ switch((*ent)->bal) { case R_EQUILIBRATED: (*ent)->bal = RIGHTSLANTED; return(0); case RIGHTSLANTED: (*ent)->bal = R_REBALANCE; return(1); case R_REBALANCE: /* rebalance */ if((ent1 = (*ent)->right)->bal == R_REBALANCE) { /* single RR rotation */ (*ent)->right = ent1->left; ent1->left = *ent; (*ent)->bal = RIGHTSLANTED; *ent = ent1; } else { /* double RL rotation */ ent2 = ent1->left; ent1->left = ent2->right; ent2->right = ent1; (*ent)->right = ent2->left; ent2->left = *ent; (*ent)->bal = (ent2->bal == R_REBALANCE) ? R_EQUILIBRATED : RIGHTSLANTED; ent1->bal = (ent2->bal == R_EQUILIBRATED) ? R_REBALANCE : RIGHTSLANTED; *ent = ent2; } (*ent)->bal = RIGHTSLANTED; return(0); } }