Blob


1 #include "rc.h"
2 #include "exec.h"
3 #include "fns.h"
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];
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 }
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 }
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 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 }
90 void
91 setvar(char *name, word *val)
92 {
93 _setvar(name, val, 1);
94 }
96 void
97 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;
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;
127 _setvar("path", w, 0);
130 char*
131 list2strcolon(word *words)
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++=':';
144 if(s==value)
145 *s='\0';
146 else s[-1]='\0';
147 return value;
149 void
150 littlepath(var *v)
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 */
163 void
164 pathinit(void)
166 var *v;
168 v = gvlook("path");
169 v->changefn = littlepath;
170 v = gvlook("PATH");
171 v->changefn = bigpath;
172 bigpath(v);