| #include "rc.h" |
| #include "exec.h" |
| #include "fns.h" |
| int hash(char *s, int n) |
| { |
| register int h=0, i=1; |
| while(*s) h+=*s++*i++; |
| h%=n; |
| return h<0?h+n:h; |
| } |
| #define NKW 30 |
| struct kw{ |
| char *name; |
| int type; |
| struct kw *next; |
| }*kw[NKW]; |
| void kenter(int type, char *name) |
| { |
| register int h=hash(name, NKW); |
| register struct kw *p=new(struct kw); |
| p->type=type; |
| p->name=name; |
| p->next=kw[h]; |
| kw[h]=p; |
| } |
| void kinit(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) |
| { |
| register struct var *v=vlook(name); |
| freewords(v->val); |
| v->val=val; |
| v->changed=1; |
| if(callfn && v->changefn) |
| v->changefn(v); |
| } |
| void setvar(char *name, word *val) |
| { |
| _setvar(name, val, 1); |
| } |
| void bigpath(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); |
| } |
| void littlepath(var *v) |
| { |
| /* convert $path to $PATH */ |
| char *p; |
| word *w; |
| |
| p = _list2str(v->val, ':'); |
| w = new(word); |
| w->word = p; |
| w->next = nil; |
| _setvar("PATH", w, 1); /* 1: recompute $path to expose colon problems */ |
| } |
| void pathinit(void) |
| { |
| var *v; |
| |
| v = gvlook("path"); |
| v->changefn = littlepath; |
| v = gvlook("PATH"); |
| v->changefn = bigpath; |
| bigpath(v); |
| } |