9base

revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log | Files | Refs | README | LICENSE

var.c (2561B)


      1 #include "rc.h"
      2 #include "exec.h"
      3 #include "fns.h"
      4 
      5 int
      6 hash(char *s, int n)
      7 {
      8 	int h = 0, i = 1;
      9 	while(*s) h+=*s++*i++;
     10 	h%=n;
     11 	return h<0?h+n:h;
     12 }
     13 #define	NKW	30
     14 struct kw{
     15 	char *name;
     16 	int type;
     17 	struct kw *next;
     18 }*kw[NKW];
     19 
     20 void
     21 kenter(int type, char *name)
     22 {
     23 	int h = hash(name, NKW);
     24 	struct kw *p = new(struct kw);
     25 	p->type = type;
     26 	p->name = name;
     27 	p->next = kw[h];
     28 	kw[h] = p;
     29 }
     30 
     31 void
     32 kinit(void)
     33 {
     34 	kenter(FOR, "for");
     35 	kenter(IN, "in");
     36 	kenter(WHILE, "while");
     37 	kenter(IF, "if");
     38 	kenter(NOT, "not");
     39 	kenter(TWIDDLE, "~");
     40 	kenter(BANG, "!");
     41 	kenter(SUBSHELL, "@");
     42 	kenter(SWITCH, "switch");
     43 	kenter(FN, "fn");
     44 }
     45 
     46 tree*
     47 klook(char *name)
     48 {
     49 	struct kw *p;
     50 	tree *t = token(name, WORD);
     51 	for(p = kw[hash(name, NKW)];p;p = p->next)
     52 		if(strcmp(p->name, name)==0){
     53 			t->type = p->type;
     54 			t->iskw = 1;
     55 			break;
     56 		}
     57 	return t;
     58 }
     59 
     60 var*
     61 gvlook(char *name)
     62 {
     63 	int h = hash(name, NVAR);
     64 	var *v;
     65 	for(v = gvar[h];v;v = v->next) if(strcmp(v->name, name)==0) return v;
     66 	return gvar[h] = newvar(strdup(name), gvar[h]);
     67 }
     68 
     69 var*
     70 vlook(char *name)
     71 {
     72 	var *v;
     73 	if(runq)
     74 		for(v = runq->local;v;v = v->next)
     75 			if(strcmp(v->name, name)==0) return v;
     76 	return gvlook(name);
     77 }
     78 
     79 void
     80 _setvar(char *name, word *val, int callfn)
     81 {
     82 	struct var *v = vlook(name);
     83 	freewords(v->val);
     84 	v->val=val;
     85 	v->changed=1;
     86 	if(callfn && v->changefn)
     87 		v->changefn(v);
     88 }
     89 
     90 void
     91 setvar(char *name, word *val)
     92 {
     93 	_setvar(name, val, 1);
     94 }
     95 
     96 void
     97 bigpath(var *v)
     98 {
     99 	/* convert $PATH to $path */
    100 	char *p, *q;
    101 	word **l, *w;
    102 
    103 	if(v->val == nil){
    104 		_setvar("path", nil, 0);
    105 		return;
    106 	}
    107 	p = v->val->word;
    108 	w = nil;
    109 	l = &w;
    110 	/*
    111 	 * Doesn't handle escaped colon nonsense.
    112 	 */
    113 	if(p[0] == 0)
    114 		p = nil;
    115 	while(p){
    116 		q = strchr(p, ':');
    117 		if(q)
    118 			*q = 0;
    119 		*l = newword(p[0] ? p : ".", nil);
    120 		l = &(*l)->next;
    121 		if(q){
    122 			*q = ':';
    123 			p = q+1;
    124 		}else
    125 			p = nil;
    126 	}
    127 	_setvar("path", w, 0);
    128 }
    129 
    130 char*
    131 list2strcolon(word *words)
    132 {
    133 	char *value, *s, *t;
    134 	int len = 0;
    135 	word *ap;
    136 	for(ap = words;ap;ap = ap->next)
    137 		len+=1+strlen(ap->word);
    138 	value = emalloc(len+1);
    139 	s = value;
    140 	for(ap = words;ap;ap = ap->next){
    141 		for(t = ap->word;*t;) *s++=*t++;
    142 		*s++=':';
    143 	}
    144 	if(s==value)
    145 		*s='\0';
    146 	else s[-1]='\0';
    147 	return value;
    148 }
    149 void
    150 littlepath(var *v)
    151 {
    152 	/* convert $path to $PATH */
    153 	char *p;
    154 	word *w;
    155 
    156 	p = list2strcolon(v->val);
    157 	w = new(word);
    158 	w->word = p;
    159 	w->next = nil;
    160 	_setvar("PATH", w, 1);	/* 1: recompute $path to expose colon problems */
    161 }
    162 
    163 void
    164 pathinit(void)
    165 {
    166 	var *v;
    167 
    168 	v = gvlook("path");
    169 	v->changefn = littlepath;
    170 	v = gvlook("PATH");
    171 	v->changefn = bigpath;
    172 	bigpath(v);
    173 }