Blob
1 #include "rc.h"2 #include "exec.h"3 #include "fns.h"5 int6 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 3014 struct kw{15 char *name;16 int type;17 struct kw *next;18 }*kw[NKW];20 void21 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 }31 void32 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 }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 }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 }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 }79 void80 _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 }90 void91 setvar(char *name, word *val)92 {93 _setvar(name, val, 1);94 }96 void97 bigpath(var *v)98 {99 /* convert $PATH to $path */100 char *p, *q;101 word **l, *w;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 }else125 p = nil;126 }127 _setvar("path", w, 0);128 }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 void150 littlepath(var *v)151 {152 /* convert $path to $PATH */153 char *p;154 word *w;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 }163 void164 pathinit(void)165 {166 var *v;168 v = gvlook("path");169 v->changefn = littlepath;170 v = gvlook("PATH");171 v->changefn = bigpath;172 bigpath(v);173 }