var.c (2561B)
1 #include "rc.h" 2 #include "exec.h" 3 #include "fns.h" 4 5 int 6 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 30 14 struct kw{ 15 char *name; 16 int type; 17 struct kw *next; 18 }*kw[NKW]; 19 20 void 21 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 } 30 31 void 32 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 } 45 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 } 59 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 } 68 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 } 78 79 void 80 _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 } 89 90 void 91 setvar(char *name, word *val) 92 { 93 _setvar(name, val, 1); 94 } 95 96 void 97 bigpath(var *v) 98 { 99 /* convert $PATH to $path */ 100 char *p, *q; 101 word **l, *w; 102 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 }else 125 p = nil; 126 } 127 _setvar("path", w, 0); 128 } 129 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 void 150 littlepath(var *v) 151 { 152 /* convert $path to $PATH */ 153 char *p; 154 word *w; 155 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 } 162 163 void 164 pathinit(void) 165 { 166 var *v; 167 168 v = gvlook("path"); 169 v->changefn = littlepath; 170 v = gvlook("PATH"); 171 v->changefn = bigpath; 172 bigpath(v); 173 }