#include "rc.h" #include "exec.h" #include "fns.h" int hash(char *s, int n) { 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) { int h = hash(name, NKW); 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) { 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); } 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; } void littlepath(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 */ } void pathinit(void) { var *v; v = gvlook("path"); v->changefn = littlepath; v = gvlook("PATH"); v->changefn = bigpath; bigpath(v); }