code.c 7.6 KB

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