rminnichmerge57758a716 years agoHistory
173 lines · 2.5 KB · C
RawDownload
#include "rc.h"#include "exec.h"#include "fns.h" inthash(char *s, int n){	int h = 0, i = 1;	while(*s) h+=*s++*i++;	h%=n;	return h<0?h+n:h;}#define	NKW	30struct kw{	char *name;	int type;	struct kw *next;}*kw[NKW]; voidkenter(int type, char *name){	int h = hash(name, NKW);	struct kw *p = new(struct kw);	p->type = type;	p->name = name;	p->next = kw[h];	kw[h] = p;} voidkinit(void){	kenter(FOR, "for");	kenter(IN, "in");	kenter(WHILE, "while");	kenter(IF, "if");	kenter(NOT, "not");	kenter(TWIDDLE, "~");	kenter(BANG, "!");	kenter(SUBSHELL, "@");	kenter(SWITCH, "switch");	kenter(FN, "fn");} tree*klook(char *name){	struct kw *p;	tree *t = token(name, WORD);	for(p = kw[hash(name, NKW)];p;p = p->next)		if(strcmp(p->name, name)==0){			t->type = p->type;			t->iskw = 1;			break;		}	return t;} var*gvlook(char *name){	int h = hash(name, NVAR);	var *v;	for(v = gvar[h];v;v = v->next) if(strcmp(v->name, name)==0) return v;	return gvar[h] = newvar(strdup(name), gvar[h]);} var*vlook(char *name){	var *v;	if(runq)		for(v = runq->local;v;v = v->next)			if(strcmp(v->name, name)==0) return v;	return gvlook(name);} void_setvar(char *name, word *val, int callfn){	struct var *v = vlook(name);	freewords(v->val);	v->val=val;	v->changed=1;	if(callfn && v->changefn)		v->changefn(v);} voidsetvar(char *name, word *val){	_setvar(name, val, 1);} voidbigpath(var *v){	/* convert $PATH to $path */	char *p, *q;	word **l, *w; 	if(v->val == nil){		_setvar("path", nil, 0);		return;	}	p = v->val->word;	w = nil;	l = &w;	/*	 * Doesn't handle escaped colon nonsense.	 */	if(p[0] == 0)		p = nil;	while(p){		q = strchr(p, ':');		if(q)			*q = 0;		*l = newword(p[0] ? p : ".", nil);		l = &(*l)->next;		if(q){			*q = ':';			p = q+1;		}else			p = nil;	}	_setvar("path", w, 0);} char*list2strcolon(word *words){	char *value, *s, *t;	int len = 0;	word *ap;	for(ap = words;ap;ap = ap->next)		len+=1+strlen(ap->word);	value = emalloc(len+1);	s = value;	for(ap = words;ap;ap = ap->next){		for(t = ap->word;*t;) *s++=*t++;		*s++=':';	}	if(s==value)		*s='\0';	else s[-1]='\0';	return value;}voidlittlepath(var *v){	/* convert $path to $PATH */	char *p;	word *w; 	p = list2strcolon(v->val);	w = new(word);	w->word = p;	w->next = nil;	_setvar("PATH", w, 1);	/* 1: recompute $path to expose colon problems */} voidpathinit(void){	var *v; 	v = gvlook("path");	v->changefn = littlepath;	v = gvlook("PATH");	v->changefn = bigpath;	bigpath(v);}