var.c - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
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) retu… | |
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 co… | |
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 } |