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