code.c 8.0 KB

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