xref: /inferno-os/utils/rcsh/var.c (revision 556f8a312ed1b20f8ff25c104928646828e8b05c)
1 #include "rc.h"
2 #include "y.tab.h"
3 
4 extern char **_environ;
5 
6 typedef struct Kw	Kw;
7 
8 #define	NKW	30
9 #define NVAR	521
10 
11 struct Kw{
12 	char	*name;
13 	int	type;
14 	Kw	*next;
15 };
16 
17 void	updenvlocal(Var *v);
18 void	addenv(Var *v);
19 
20 Kw	*kw[NKW];
21 Var	*gvar[NVAR];
22 
23 int
24 hash(char *s, int n)
25 {
26 	int h=0, i=1;
27 
28 	while(*s)
29 		h+=*s++*i++;
30 	h%=n;
31 	return h<0?h+n:h;
32 }
33 
34 void
35 kenter(int type, char *name)
36 {
37 	int h=hash(name, NKW);
38 	Kw *p=new(Kw);
39 	p->type=type;
40 	p->name=name;
41 	p->next=kw[h];
42 	kw[h]=p;
43 }
44 
45 void
46 vinit(void)
47 {
48 	char **env, *name, *val, *p;
49 	int i;
50 	Word *w;
51 	Io *f;
52 	int n;
53 	Var *v;
54 
55 	env = _environ;
56 	for(i=0; env[i]; free(name), i++) {
57 		name = strdup(env[i]);
58 		p = strchr(name, '=');
59 		if(p == 0 || p == name)
60 			continue;
61 		*p = 0;
62 		val = p+1;
63 		n = strlen(val);
64 		if(n == 0)
65 			continue;
66 
67 		if(strncmp(name, "fn#", 3)!=0) {
68 			/* variable */
69 			w = 0;
70 			p = val+n-1;
71 			while(*p) {
72 				if(*p == IWS)
73 					*p-- = 0;
74 				for(; *p && *p != IWS; p--)
75 					;
76 				w=newword(p+1, w);
77 			}
78 			setvar(name, w);
79 			vlook(name)->changed=0;
80 		} else {
81 			/* function */
82 			f = opencore(val, n);
83 			execcmds(f);
84 		}
85 	}
86 	v = vlook("path");
87 	p = getenv("path");
88 	if(v->val == 0 && p)
89 		v->val = newword(p, 0);
90 }
91 
92 
93 Tree *
94 klook(char *name)
95 {
96 	Kw *p;
97 	Tree *t=token(name, WORD);
98 	for(p=kw[hash(name, NKW)];p;p=p->next) {
99 		if(strcmp(p->name, name)==0){
100 			t->type=p->type;
101 			t->iskw=1;
102 			break;
103 		}
104 	}
105 	return t;
106 }
107 
108 Var *
109 gvlook(char *name)
110 {
111 	int h=hash(name, NVAR);
112 	Var *v;
113 	for(v=gvar[h]; v; v=v->next)
114 		if(strcmp(v->name, name)==0)
115 			return v;
116 
117 	return gvar[h]=newvar(strdup(name), gvar[h]);
118 }
119 
120 Var *
121 vlook(char *name)
122 {
123 	Var *v;
124 	if(runq)
125 		for(v=runq->local; v; v=v->next)
126 			if(strcmp(v->name, name)==0)
127 				return v;
128 	return gvlook(name);
129 }
130 
131 void
132 setvar(char *name, Word *val)
133 {
134 	Var *v=vlook(name);
135 	freewords(v->val);
136 	v->val=val;
137 	v->changed=1;
138 }
139 
140 Var *
141 newvar(char *name, Var *next)
142 {
143 	Var *v=new(Var);
144 	v->name=name;
145 	v->val=0;
146 	v->fn=0;
147 	v->changed=0;
148 	v->fnchanged=0;
149 	v->next=next;
150 	return v;
151 }
152 
153 
154 void
155 execfinit(void)
156 {
157 }
158 
159 void
160 updenv(void)
161 {
162 	Var *v, **h;
163 
164 	for(h=gvar;h!=&gvar[NVAR];h++)
165 		for(v=*h;v;v=v->next)
166 			addenv(v);
167 
168 	if(runq)
169 		updenvlocal(runq->local);
170 }
171 
172 static void
173 envput(char *var, char  *val)
174 {
175 	int i, n;
176 	char *e;
177 	char buf[256];
178 
179 	snprint(buf, sizeof(buf), "%s=%s", var, val);
180 	n = strlen(var);
181 	for(i = 0;;i++){
182 		e = environ[i];
183 		if(e == 0)
184 			break;
185 		if(strncmp(e, var, n) == 0){
186 			free(e);
187 			environ[i] = strdup(buf);
188 			return;
189 		}
190 	}
191 	environ = realloc(environ, (i+2)*sizeof(char*));
192 	environ[i++] = strdup(buf);
193 	environ[i] = 0;
194 }
195 
196 void
197 addenv(Var *v)
198 {
199 	char buf[100], *p;
200 	Io *f;
201 	Word *w;
202 	int i, n;
203 
204 	if(v->changed){
205 		v->changed=0;
206 		p = 0;
207 		n = 0;
208 		if(v->val) {
209 			for(w=v->val; w; w=w->next) {
210 				i = strlen(w->word);
211 				p = realloc(p, n+i+1);
212 				memmove(p+n, w->word, i);
213 				n+=i;
214 				p[n++] = IWS;
215 			}
216 			p[n-1] = 0;
217 			envput(v->name, p);
218 		} else
219 			envput(v->name, "");
220 		free(p);
221 	}
222 
223 	if(v->fnchanged){
224 		v->fnchanged=0;
225 		snprint(buf, sizeof(buf), "fn#%s", v->name);
226 		f = openstr();
227 		pfmt(f, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
228 		envput(buf, f->strp);
229 		closeio(f);
230 	}
231 }
232 
233 void
234 updenvlocal(Var *v)
235 {
236 	if(v){
237 		updenvlocal(v->next);
238 		addenv(v);
239 	}
240 }
241