Introduction
Introduction Statistics Contact Development Disclaimer Help
code.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
code.c (8287B)
---
1 #include "rc.h"
2 #include "io.h"
3 #include "exec.h"
4 #include "fns.h"
5 #include "getflags.h"
6 #define c0 t->child[0]
7 #define c1 t->child[1]
8 #define c2 t->child[2]
9 int codep, ncode;
10 #define emitf(x) ((void)(codep!=ncode || morecode()), codebuf[cod…
11 #define emiti(x) ((void)(codep!=ncode || morecode()), codebuf[cod…
12 #define emits(x) ((void)(codep!=ncode || morecode()), codebuf[cod…
13 void stuffdot(int);
14 char *fnstr(tree*);
15 void outcode(tree*, int);
16 void codeswitch(tree*, int);
17 int iscase(tree*);
18 code *codecopy(code*);
19 void codefree(code*);
20
21 int
22 morecode(void)
23 {
24 ncode+=100;
25 codebuf = (code *)realloc((char *)codebuf, ncode*sizeof codebuf[…
26 if(codebuf==0)
27 panic("Can't realloc %d bytes in morecode!",
28 ncode*sizeof codebuf[0]);
29 memset(codebuf+ncode-100, 0, 100*sizeof codebuf[0]);
30 return 0;
31 }
32
33 void
34 stuffdot(int a)
35 {
36 if(a<0 || codep<=a)
37 panic("Bad address %d in stuffdot", a);
38 codebuf[a].i = codep;
39 }
40
41 int
42 compile(tree *t)
43 {
44 ncode = 100;
45 codebuf = (code *)emalloc(ncode*sizeof codebuf[0]);
46 codep = 0;
47 emiti(0); /* reference count */
48 outcode(t, flag['e']?1:0);
49 if(nerror){
50 efree((char *)codebuf);
51 return 0;
52 }
53 readhere();
54 emitf(Xreturn);
55 emitf(0);
56 return 1;
57 }
58
59 void
60 cleanhere(char *f)
61 {
62 emitf(Xdelhere);
63 emits(strdup(f));
64 }
65
66 char*
67 fnstr(tree *t)
68 {
69 io *f = openstr();
70 char *v;
71 extern char nl;
72 char svnl = nl;
73 nl=';';
74 pfmt(f, "%t", t);
75 nl = svnl;
76 v = f->strp;
77 f->strp = 0;
78 closeio(f);
79 return v;
80 }
81
82 void
83 outcode(tree *t, int eflag)
84 {
85 int p, q;
86 tree *tt;
87 if(t==0)
88 return;
89 if(t->type!=NOT && t->type!=';')
90 runq->iflast = 0;
91 switch(t->type){
92 default:
93 pfmt(err, "bad type %d in outcode\n", t->type);
94 break;
95 case '$':
96 emitf(Xmark);
97 outcode(c0, eflag);
98 emitf(Xdol);
99 break;
100 case '"':
101 emitf(Xmark);
102 outcode(c0, eflag);
103 emitf(Xqdol);
104 break;
105 case SUB:
106 emitf(Xmark);
107 outcode(c0, eflag);
108 emitf(Xmark);
109 outcode(c1, eflag);
110 emitf(Xsub);
111 break;
112 case '&':
113 emitf(Xasync);
114 if(havefork){
115 p = emiti(0);
116 outcode(c0, eflag);
117 emitf(Xexit);
118 stuffdot(p);
119 } else
120 emits(fnstr(c0));
121 break;
122 case ';':
123 outcode(c0, eflag);
124 outcode(c1, eflag);
125 break;
126 case '^':
127 emitf(Xmark);
128 outcode(c1, eflag);
129 emitf(Xmark);
130 outcode(c0, eflag);
131 emitf(Xconc);
132 break;
133 case '`':
134 emitf(Xbackq);
135 if(havefork){
136 p = emiti(0);
137 outcode(c0, 0);
138 emitf(Xexit);
139 stuffdot(p);
140 } else
141 emits(fnstr(c0));
142 break;
143 case ANDAND:
144 outcode(c0, 0);
145 emitf(Xtrue);
146 p = emiti(0);
147 outcode(c1, eflag);
148 stuffdot(p);
149 break;
150 case ARGLIST:
151 outcode(c1, eflag);
152 outcode(c0, eflag);
153 break;
154 case BANG:
155 outcode(c0, eflag);
156 emitf(Xbang);
157 break;
158 case PCMD:
159 case BRACE:
160 outcode(c0, eflag);
161 break;
162 case COUNT:
163 emitf(Xmark);
164 outcode(c0, eflag);
165 emitf(Xcount);
166 break;
167 case FN:
168 emitf(Xmark);
169 outcode(c0, eflag);
170 if(c1){
171 emitf(Xfn);
172 p = emiti(0);
173 emits(fnstr(c1));
174 outcode(c1, eflag);
175 emitf(Xunlocal); /* get rid of $* */
176 emitf(Xreturn);
177 stuffdot(p);
178 }
179 else
180 emitf(Xdelfn);
181 break;
182 case IF:
183 outcode(c0, 0);
184 emitf(Xif);
185 p = emiti(0);
186 outcode(c1, eflag);
187 emitf(Xwastrue);
188 stuffdot(p);
189 break;
190 case NOT:
191 if(!runq->iflast)
192 yyerror("`if not' does not follow `if(...)'");
193 emitf(Xifnot);
194 p = emiti(0);
195 outcode(c0, eflag);
196 stuffdot(p);
197 break;
198 case OROR:
199 outcode(c0, 0);
200 emitf(Xfalse);
201 p = emiti(0);
202 outcode(c1, eflag);
203 stuffdot(p);
204 break;
205 case PAREN:
206 outcode(c0, eflag);
207 break;
208 case SIMPLE:
209 emitf(Xmark);
210 outcode(c0, eflag);
211 emitf(Xsimple);
212 if(eflag)
213 emitf(Xeflag);
214 break;
215 case SUBSHELL:
216 emitf(Xsubshell);
217 if(havefork){
218 p = emiti(0);
219 outcode(c0, eflag);
220 emitf(Xexit);
221 stuffdot(p);
222 } else
223 emits(fnstr(c0));
224 if(eflag)
225 emitf(Xeflag);
226 break;
227 case SWITCH:
228 codeswitch(t, eflag);
229 break;
230 case TWIDDLE:
231 emitf(Xmark);
232 outcode(c1, eflag);
233 emitf(Xmark);
234 outcode(c0, eflag);
235 emitf(Xmatch);
236 if(eflag)
237 emitf(Xeflag);
238 break;
239 case WHILE:
240 q = codep;
241 outcode(c0, 0);
242 if(q==codep)
243 emitf(Xsettrue); /* empty condition == wh…
244 emitf(Xtrue);
245 p = emiti(0);
246 outcode(c1, eflag);
247 emitf(Xjump);
248 emiti(q);
249 stuffdot(p);
250 break;
251 case WORDS:
252 outcode(c1, eflag);
253 outcode(c0, eflag);
254 break;
255 case FOR:
256 emitf(Xmark);
257 if(c1){
258 outcode(c1, eflag);
259 emitf(Xglob);
260 }
261 else{
262 emitf(Xmark);
263 emitf(Xword);
264 emits(strdup("*"));
265 emitf(Xdol);
266 }
267 emitf(Xmark); /* dummy value for Xlocal */
268 emitf(Xmark);
269 outcode(c0, eflag);
270 emitf(Xlocal);
271 p = emitf(Xfor);
272 q = emiti(0);
273 outcode(c2, eflag);
274 emitf(Xjump);
275 emiti(p);
276 stuffdot(q);
277 emitf(Xunlocal);
278 break;
279 case WORD:
280 emitf(Xword);
281 emits(strdup(t->str));
282 break;
283 case DUP:
284 if(t->rtype==DUPFD){
285 emitf(Xdup);
286 emiti(t->fd0);
287 emiti(t->fd1);
288 }
289 else{
290 emitf(Xclose);
291 emiti(t->fd0);
292 }
293 outcode(c1, eflag);
294 emitf(Xpopredir);
295 break;
296 case PIPEFD:
297 emitf(Xpipefd);
298 emiti(t->rtype);
299 if(havefork){
300 p = emiti(0);
301 outcode(c0, eflag);
302 emitf(Xexit);
303 stuffdot(p);
304 } else {
305 emits(fnstr(c0));
306 }
307 break;
308 case REDIR:
309 emitf(Xmark);
310 outcode(c0, eflag);
311 emitf(Xglob);
312 switch(t->rtype){
313 case APPEND:
314 emitf(Xappend);
315 break;
316 case WRITE:
317 emitf(Xwrite);
318 break;
319 case READ:
320 case HERE:
321 emitf(Xread);
322 break;
323 case RDWR:
324 emitf(Xrdwr);
325 break;
326 }
327 emiti(t->fd0);
328 outcode(c1, eflag);
329 emitf(Xpopredir);
330 break;
331 case '=':
332 tt = t;
333 for(;t && t->type=='=';t = c2);
334 if(t){
335 for(t = tt;t->type=='=';t = c2){
336 emitf(Xmark);
337 outcode(c1, eflag);
338 emitf(Xmark);
339 outcode(c0, eflag);
340 emitf(Xlocal);
341 }
342 outcode(t, eflag);
343 for(t = tt; t->type=='='; t = c2)
344 emitf(Xunlocal);
345 }
346 else{
347 for(t = tt;t;t = c2){
348 emitf(Xmark);
349 outcode(c1, eflag);
350 emitf(Xmark);
351 outcode(c0, eflag);
352 emitf(Xassign);
353 }
354 }
355 t = tt; /* so tests below will work */
356 break;
357 case PIPE:
358 emitf(Xpipe);
359 emiti(t->fd0);
360 emiti(t->fd1);
361 if(havefork){
362 p = emiti(0);
363 q = emiti(0);
364 outcode(c0, eflag);
365 emitf(Xexit);
366 stuffdot(p);
367 } else {
368 emits(fnstr(c0));
369 q = emiti(0);
370 }
371 outcode(c1, eflag);
372 emitf(Xreturn);
373 stuffdot(q);
374 emitf(Xpipewait);
375 break;
376 }
377 if(t->type!=NOT && t->type!=';')
378 runq->iflast = t->type==IF;
379 else if(c0) runq->iflast = c0->type==IF;
380 }
381 /*
382 * switch code looks like this:
383 * Xmark
384 * (get switch value)
385 * Xjump 1f
386 * out: Xjump leave
387 * 1: Xmark
388 * (get case values)
389 * Xcase 1f
390 * (commands)
391 * Xjump out
392 * 1: Xmark
393 * (get case values)
394 * Xcase 1f
395 * (commands)
396 * Xjump out
397 * 1:
398 * leave:
399 * Xpopm
400 */
401
402 void
403 codeswitch(tree *t, int eflag)
404 {
405 int leave; /* patch jump address to leave switch …
406 int out; /* jump here to leave switch */
407 int nextcase; /* patch jump address to next case */
408 tree *tt;
409 if(c1->child[0]==nil
410 || c1->child[0]->type!=';'
411 || !iscase(c1->child[0]->child[0])){
412 yyerror("case missing in switch");
413 return;
414 }
415 emitf(Xmark);
416 outcode(c0, eflag);
417 emitf(Xjump);
418 nextcase = emiti(0);
419 out = emitf(Xjump);
420 leave = emiti(0);
421 stuffdot(nextcase);
422 t = c1->child[0];
423 while(t->type==';'){
424 tt = c1;
425 emitf(Xmark);
426 for(t = c0->child[0];t->type==ARGLIST;t = c0) outcode(c1…
427 emitf(Xcase);
428 nextcase = emiti(0);
429 t = tt;
430 for(;;){
431 if(t->type==';'){
432 if(iscase(c0)) break;
433 outcode(c0, eflag);
434 t = c1;
435 }
436 else{
437 if(!iscase(t)) outcode(t, eflag);
438 break;
439 }
440 }
441 emitf(Xjump);
442 emiti(out);
443 stuffdot(nextcase);
444 }
445 stuffdot(leave);
446 emitf(Xpopm);
447 }
448
449 int
450 iscase(tree *t)
451 {
452 if(t->type!=SIMPLE)
453 return 0;
454 do t = c0; while(t->type==ARGLIST);
455 return t->type==WORD && !t->quoted && strcmp(t->str, "case")==0;
456 }
457
458 code*
459 codecopy(code *cp)
460 {
461 cp[0].i++;
462 return cp;
463 }
464
465 void
466 codefree(code *cp)
467 {
468 code *p;
469 if(--cp[0].i!=0)
470 return;
471 for(p = cp+1;p->f;p++){
472 if(p->f==Xappend || p->f==Xclose || p->f==Xread || p->f=…
473 || p->f==Xrdwr
474 || p->f==Xasync || p->f==Xbackq || p->f==Xcase || p->f==…
475 || p->f==Xfor || p->f==Xjump
476 || p->f==Xsubshell || p->f==Xtrue) p++;
477 else if(p->f==Xdup || p->f==Xpipefd) p+=2;
478 else if(p->f==Xpipe) p+=4;
479 else if(p->f==Xword || p->f==Xdelhere) efree((++p)->s);
480 else if(p->f==Xfn){
481 efree(p[2].s);
482 p+=2;
483 }
484 }
485 efree((char *)cp);
486 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.