Blob
1 #include "rc.h"2 #include "exec.h"3 #include "fns.h"4 int hash(char *s, int n)5 {6 register int h=0, i=1;7 while(*s) h+=*s++*i++;8 h%=n;9 return h<0?h+n:h;10 }11 #define NKW 3012 struct kw{13 char *name;14 int type;15 struct kw *next;16 }*kw[NKW];17 void kenter(int type, char *name)18 {19 register int h=hash(name, NKW);20 register struct kw *p=new(struct kw);21 p->type=type;22 p->name=name;23 p->next=kw[h];24 kw[h]=p;25 }26 void kinit(void){27 kenter(FOR, "for");28 kenter(IN, "in");29 kenter(WHILE, "while");30 kenter(IF, "if");31 kenter(NOT, "not");32 kenter(TWIDDLE, "~");33 kenter(BANG, "!");34 kenter(SUBSHELL, "@");35 kenter(SWITCH, "switch");36 kenter(FN, "fn");37 }38 tree *klook(char *name)39 {40 struct kw *p;41 tree *t=token(name, WORD);42 for(p=kw[hash(name, NKW)];p;p=p->next)43 if(strcmp(p->name, name)==0){44 t->type=p->type;45 t->iskw=1;46 break;47 }48 return t;49 }50 var *gvlook(char *name)51 {52 int h=hash(name, NVAR);53 var *v;54 for(v=gvar[h];v;v=v->next) if(strcmp(v->name, name)==0) return v;55 return gvar[h]=newvar(strdup(name), gvar[h]);56 }57 var *vlook(char *name)58 {59 var *v;60 if(runq)61 for(v=runq->local;v;v=v->next)62 if(strcmp(v->name, name)==0) return v;63 return gvlook(name);64 }65 void _setvar(char *name, word *val, int callfn)66 {67 register struct var *v=vlook(name);68 freewords(v->val);69 v->val=val;70 v->changed=1;71 if(callfn && v->changefn)72 v->changefn(v);73 }74 void setvar(char *name, word *val)75 {76 _setvar(name, val, 1);77 }78 void bigpath(var *v)79 {80 /* convert $PATH to $path */81 char *p, *q;82 word **l, *w;84 if(v->val == nil){85 _setvar("path", nil, 0);86 return;87 }88 p = v->val->word;89 w = nil;90 l = &w;91 /*92 * Doesn't handle escaped colon nonsense.93 */94 if(p[0] == 0)95 p = nil;96 while(p){97 q = strchr(p, ':');98 if(q)99 *q = 0;100 *l = newword(p[0] ? p : ".", nil);101 l = &(*l)->next;102 if(q){103 *q = ':';104 p = q+1;105 }else106 p = nil;107 }108 _setvar("path", w, 0);109 }110 void littlepath(var *v)111 {112 /* convert $path to $PATH */113 char *p;114 word *w;116 p = _list2str(v->val, ':');117 w = new(word);118 w->word = p;119 w->next = nil;120 _setvar("PATH", w, 1); /* 1: recompute $path to expose colon problems */121 }122 void pathinit(void)123 {124 var *v;126 v = gvlook("path");127 v->changefn = littlepath;128 v = gvlook("PATH");129 v->changefn = bigpath;130 bigpath(v);131 }