getline.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. *
  5. * Author: Hans van Staveren
  6. */
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include "param.h"
  10. #include "types.h"
  11. #include "tes.h"
  12. #include "line.h"
  13. #include "lookup.h"
  14. #include "alloc.h"
  15. #include "proinf.h"
  16. #include "getline.h"
  17. #include "util.h"
  18. #include "process.h"
  19. #include "reg.h"
  20. #include <em_spec.h>
  21. #include <em_pseu.h>
  22. #include <em_flag.h>
  23. #include <em_mes.h>
  24. #include "ext.h"
  25. static short tabval; /* temp store for shorts */
  26. static offset tabval2; /* temp store for offsets */
  27. static char string[IDL+1]; /* temp store for names */
  28. /*
  29. * The next constants are close to sp_cend for fast switches
  30. */
  31. #define INST 256 /* instruction: number in tabval */
  32. #define PSEU 257 /* pseudo: number in tabval */
  33. #define ILBX 258 /* label: number in tabval */
  34. #define DLBX 259 /* symbol: name in string[] */
  35. #define CSTX1 260 /* short constant: stored in tabval */
  36. #define CSTX2 261 /* offset: value in tabval2 */
  37. #define VALX1 262 /* symbol+short: in string[] and tabval */
  38. #define VALX2 263 /* symbol+offset: in string[] and tabval2 */
  39. #define ATEOF 264 /* bumped into end of file */
  40. #define readbyte getchar
  41. short readshort()
  42. {
  43. int l_byte, h_byte;
  44. l_byte = readbyte();
  45. h_byte = readbyte();
  46. if ( h_byte>=128 ) h_byte -= 256 ;
  47. return l_byte | (h_byte*256) ;
  48. }
  49. #ifdef LONGOFF
  50. offset readoffset()
  51. {
  52. long l;
  53. int h_byte;
  54. l = readbyte();
  55. l |= ((unsigned) readbyte())*256 ;
  56. l |= readbyte()*256L*256L ;
  57. h_byte = readbyte() ;
  58. if ( h_byte>=128 ) h_byte -= 256 ;
  59. return l | (h_byte*256L*256*256L) ;
  60. }
  61. #endif
  62. void draininput()
  63. {
  64. /*
  65. * called when MES ERR is encountered.
  66. * Drain input in case it is a pipe.
  67. */
  68. while (getchar() != EOF)
  69. ;
  70. }
  71. short getint()
  72. {
  73. switch(table2()) {
  74. default: error("int expected");
  75. case CSTX1:
  76. return(tabval);
  77. }
  78. }
  79. sym_p getsym(int status)
  80. {
  81. switch(table2()) {
  82. default:
  83. error("symbol expected");
  84. case DLBX:
  85. return(symlookup(string,status,0));
  86. case sp_pnam:
  87. return(symlookup(string,status,SYMPRO));
  88. }
  89. }
  90. offset getoff()
  91. {
  92. switch (table2()) {
  93. default: error("offset expected");
  94. case CSTX1:
  95. return((offset) tabval);
  96. #ifdef LONGOFF
  97. case CSTX2:
  98. return(tabval2);
  99. #endif
  100. }
  101. }
  102. void make_string(int n)
  103. {
  104. sprintf(string,".%u",n);
  105. }
  106. void inident()
  107. {
  108. int n;
  109. char *p = string;
  110. int c;
  111. n = getint();
  112. while (n--) {
  113. c = readbyte();
  114. if (p<&string[IDL])
  115. *p++ = c;
  116. }
  117. *p++ = 0;
  118. }
  119. int table3(int n)
  120. {
  121. switch (n) {
  122. case sp_ilb1: tabval = readbyte(); return(ILBX);
  123. case sp_ilb2: tabval = readshort(); return(ILBX);
  124. case sp_dlb1: make_string(readbyte()); return(DLBX);
  125. case sp_dlb2: make_string(readshort()); return(DLBX);
  126. case sp_dnam: inident(); return(DLBX);
  127. case sp_pnam: inident(); return(n);
  128. case sp_cst2: tabval = readshort(); return(CSTX1);
  129. #ifdef LONGOFF
  130. case sp_cst4: tabval2 = readoffset(); return(CSTX2);
  131. #endif
  132. case sp_doff: if (table2()!=DLBX) error("symbol expected");
  133. switch(table2()) {
  134. default: error("offset expected");
  135. case CSTX1: return(VALX1);
  136. #ifdef LONGOFF
  137. case CSTX2: return(VALX2);
  138. #endif
  139. }
  140. default: return(n);
  141. }
  142. }
  143. int table1()
  144. {
  145. int n;
  146. n = readbyte();
  147. if (n == EOF)
  148. return(ATEOF);
  149. if ((n <= sp_lmnem) && (n >= sp_fmnem)) {
  150. tabval = n;
  151. return(INST);
  152. }
  153. if ((n <= sp_lpseu) && (n >= sp_fpseu)) {
  154. tabval = n;
  155. return(PSEU);
  156. }
  157. if ((n < sp_filb0 + sp_nilb0) && (n >= sp_filb0)) {
  158. tabval = n - sp_filb0;
  159. return(ILBX);
  160. }
  161. return(table3(n));
  162. }
  163. int table2()
  164. {
  165. int n;
  166. n = readbyte();
  167. if ((n < sp_fcst0 + sp_ncst0) && (n >= sp_fcst0)) {
  168. tabval = n - sp_zcst0;
  169. return(CSTX1);
  170. }
  171. return(table3(n));
  172. }
  173. void getlines()
  174. {
  175. line_p lnp;
  176. int instr;
  177. for(;;) {
  178. linecount++;
  179. switch(table1()) {
  180. default:
  181. error("unknown instruction byte");
  182. /* NOTREACHED */
  183. case ATEOF:
  184. if (prodepth!=0)
  185. error("procedure unterminated at eof");
  186. process();
  187. return;
  188. case INST:
  189. tstinpro();
  190. instr = tabval;
  191. break;
  192. case DLBX:
  193. lnp = newline(OPSYMBOL);
  194. lnp->l_instr = ps_sym;
  195. lnp->l_a.la_sp= symlookup(string,DEFINING,0);
  196. lnp->l_next = curpro.lastline;
  197. curpro.lastline = lnp;
  198. continue;
  199. case ILBX:
  200. tstinpro();
  201. lnp = newline(OPNUMLAB);
  202. lnp->l_instr = op_lab;
  203. lnp->l_a.la_np = numlookup((unsigned) tabval);
  204. if (lnp->l_a.la_np->n_line != (line_p) 0)
  205. error("label %u multiple defined",(unsigned) tabval);
  206. lnp->l_a.la_np->n_line = lnp;
  207. lnp->l_next = curpro.lastline;
  208. curpro.lastline = lnp;
  209. continue;
  210. case PSEU:
  211. if(inpseudo(tabval))
  212. return;
  213. continue;
  214. }
  215. /*
  216. * Now we have an instruction number in instr
  217. * There might be an operand, look for it
  218. */
  219. if ((em_flag[instr-sp_fmnem]&EM_PAR)==PAR_NO) {
  220. lnp = newline(OPNO);
  221. } else switch(table2()) {
  222. default:
  223. error("unknown offset byte");
  224. case sp_cend:
  225. lnp = newline(OPNO);
  226. break;
  227. case CSTX1:
  228. if ((em_flag[instr-sp_fmnem]&EM_PAR)!= PAR_B) {
  229. if (CANMINI(tabval))
  230. lnp = newline(tabval+Z_OPMINI);
  231. else {
  232. lnp = newline(OPSHORT);
  233. lnp->l_a.la_short = tabval;
  234. }
  235. } else {
  236. lnp = newline(OPNUMLAB);
  237. lnp->l_a.la_np = numlookup((unsigned) tabval);
  238. }
  239. break;
  240. #ifdef LONGOFF
  241. case CSTX2:
  242. lnp = newline(OPOFFSET);
  243. lnp->l_a.la_offset = tabval2;
  244. break;
  245. #endif
  246. case ILBX:
  247. tstinpro();
  248. lnp = newline(OPNUMLAB);
  249. lnp->l_a.la_np = numlookup((unsigned) tabval);
  250. break;
  251. case DLBX:
  252. lnp = newline(OPSYMBOL);
  253. lnp->l_a.la_sp = symlookup(string,OCCURRING,0);
  254. break;
  255. case sp_pnam:
  256. lnp = newline(OPSYMBOL);
  257. lnp->l_a.la_sp = symlookup(string,OCCURRING,SYMPRO);
  258. break;
  259. case VALX1:
  260. lnp = newline(OPSVAL);
  261. lnp->l_a.la_sval.lasv_sp = symlookup(string,OCCURRING,0);
  262. lnp->l_a.la_sval.lasv_short = tabval;
  263. break;
  264. #ifdef LONGOFF
  265. case VALX2:
  266. lnp = newline(OPLVAL);
  267. lnp->l_a.la_lval.lalv_sp = symlookup(string,OCCURRING,0);
  268. lnp->l_a.la_lval.lalv_offset = tabval2;
  269. break;
  270. #endif
  271. }
  272. lnp->l_instr = instr;
  273. lnp->l_next = curpro.lastline;
  274. curpro.lastline = lnp;
  275. }
  276. }
  277. void argstring(offset length, argb_p abp)
  278. {
  279. while (length--) {
  280. if (abp->ab_index == NARGBYTES)
  281. abp = abp->ab_next = newargb();
  282. abp->ab_contents[abp->ab_index++] = readbyte();
  283. }
  284. }
  285. line_p arglist(int n)
  286. {
  287. line_p lnp;
  288. arg_p ap,*app;
  289. bool moretocome;
  290. offset length;
  291. /*
  292. * creates an arglist with n elements
  293. * if n == 0 the arglist is variable and terminated by sp_cend
  294. */
  295. lnp = newline(OPLIST);
  296. app = &lnp->l_a.la_arg;
  297. moretocome = TRUE;
  298. do {
  299. switch(table2()) {
  300. default:
  301. error("unknown byte in arglist");
  302. case CSTX1:
  303. tabval2 = (offset) tabval;
  304. case CSTX2:
  305. *app = ap = newarg(ARGOFF);
  306. ap->a_a.a_offset = tabval2;
  307. app = &ap->a_next;
  308. break;
  309. case ILBX:
  310. tstinpro();
  311. *app = ap = newarg(ARGNUM);
  312. ap->a_a.a_np = numlookup((unsigned) tabval);
  313. ap->a_a.a_np->n_flags |= NUMDATA;
  314. app = &ap->a_next;
  315. break;
  316. case DLBX:
  317. *app = ap = newarg(ARGSYM);
  318. ap->a_a.a_sp = symlookup(string,OCCURRING,0);
  319. app = &ap->a_next;
  320. break;
  321. case sp_pnam:
  322. *app = ap = newarg(ARGSYM);
  323. ap->a_a.a_sp = symlookup(string,OCCURRING,SYMPRO);
  324. app = &ap->a_next;
  325. break;
  326. case VALX1:
  327. tabval2 = (offset) tabval;
  328. case VALX2:
  329. *app = ap = newarg(ARGVAL);
  330. ap->a_a.a_val.av_sp = symlookup(string,OCCURRING,0);
  331. ap->a_a.a_val.av_offset = tabval2;
  332. app = &ap->a_next;
  333. break;
  334. case sp_scon:
  335. *app = ap = newarg(ARGSTR);
  336. length = getoff();
  337. argstring(length,&ap->a_a.a_string);
  338. app = &ap->a_next;
  339. break;
  340. case sp_icon:
  341. *app = ap = newarg(ARGICN);
  342. goto casecon;
  343. case sp_ucon:
  344. *app = ap = newarg(ARGUCN);
  345. goto casecon;
  346. case sp_fcon:
  347. *app = ap = newarg(ARGFCN);
  348. casecon:
  349. length = getint();
  350. ap->a_a.a_con.ac_length = (short) length;
  351. argstring(getoff(),&ap->a_a.a_con.ac_con);
  352. app = &ap->a_next;
  353. break;
  354. case sp_cend:
  355. moretocome = FALSE;
  356. }
  357. if (n && (--n) == 0)
  358. moretocome = FALSE;
  359. } while (moretocome);
  360. return(lnp);
  361. }
  362. offset aoff(arg_p ap, int n)
  363. {
  364. while (n>0) {
  365. if (ap != (arg_p) 0)
  366. ap = ap->a_next;
  367. n--;
  368. }
  369. if (ap == (arg_p) 0)
  370. error("too few parameters");
  371. if (ap->a_typ != ARGOFF)
  372. error("offset expected");
  373. return(ap->a_a.a_offset);
  374. }
  375. int inpseudo(short n)
  376. {
  377. register line_p lnp,head,tail;
  378. short n1,n2;
  379. proinf savearea;
  380. #ifdef PSEUBETWEEN
  381. static int pcount=0;
  382. if (pcount++ >= PSEUBETWEEN && prodepth==0) {
  383. process();
  384. pcount=0;
  385. }
  386. #endif
  387. switch(n) {
  388. default:
  389. error("unknown pseudo");
  390. case ps_bss:
  391. case ps_hol:
  392. lnp = arglist(3);
  393. break;
  394. case ps_rom:
  395. case ps_con:
  396. lnp = arglist(0);
  397. break;
  398. case ps_ina:
  399. case ps_inp:
  400. case ps_exa:
  401. case ps_exp:
  402. lnp = newline(OPSYMBOL);
  403. lnp->l_a.la_sp = getsym(NOTHING);
  404. break;
  405. case ps_exc:
  406. n1 = getint(); n2 = getint();
  407. if (n1 != 0 && n2 != 0) {
  408. tail = curpro.lastline;
  409. while (--n2) tail = tail->l_next;
  410. head = tail;
  411. while (n1--) head = head->l_next;
  412. lnp = tail->l_next;
  413. tail->l_next = head->l_next;
  414. head->l_next = curpro.lastline;
  415. curpro.lastline = lnp;
  416. }
  417. lnp = newline(OPNO);
  418. break;
  419. case ps_mes:
  420. lnp = arglist(0);
  421. switch((int) aoff(lnp->l_a.la_arg,0)) {
  422. case ms_err:
  423. draininput(); exit(-1);
  424. case ms_opt:
  425. nflag = TRUE; break;
  426. case ms_emx:
  427. wordsize = aoff(lnp->l_a.la_arg,1);
  428. pointersize = aoff(lnp->l_a.la_arg,2);
  429. #ifndef LONGOFF
  430. if (wordsize>2)
  431. error("This optimizer cannot handle wordsize>2");
  432. #endif
  433. break;
  434. case ms_gto:
  435. curpro.gtoproc=1;
  436. /* Treat as empty mes ms_reg */
  437. case ms_reg:
  438. tstinpro();
  439. regvar(lnp->l_a.la_arg->a_next);
  440. oldline(lnp);
  441. lnp=newline(OPNO);
  442. n=ps_exc; /* kludge to force out this line */
  443. break;
  444. case ms_tes:
  445. tstinpro();
  446. oldline(lnp);
  447. lnp=newline(OPNO);
  448. n=ps_exc; /* kludge to force out this line */
  449. break;
  450. }
  451. break;
  452. case ps_pro:
  453. if (prodepth>0)
  454. savearea = curpro;
  455. else
  456. process();
  457. curpro.symbol = getsym(DEFINING);
  458. switch(table2()) {
  459. case sp_cend:
  460. curpro.localbytes = (offset) -1;
  461. break;
  462. case CSTX1:
  463. tabval2 = (offset) tabval;
  464. case CSTX2:
  465. curpro.localbytes = tabval2;
  466. break;
  467. default:
  468. error("bad second arg of PRO");
  469. }
  470. prodepth++;
  471. curpro.gtoproc=0;
  472. if (prodepth>1) {
  473. register i;
  474. curpro.lastline = (line_p) 0;
  475. curpro.freg = (reg_p) 0;
  476. for(i=0;i<NNUMHASH;i++)
  477. curpro.numhash[i] = (num_p) 0;
  478. getlines();
  479. curpro = savearea;
  480. prodepth--;
  481. }
  482. return(0);
  483. case ps_end:
  484. if (prodepth==0)
  485. error("END misplaced");
  486. switch(table2()) {
  487. case sp_cend:
  488. if (curpro.localbytes == (offset) -1)
  489. error("bytes for locals still unknown");
  490. break;
  491. case CSTX1:
  492. tabval2 = (offset) tabval;
  493. case CSTX2:
  494. if (curpro.localbytes != (offset) -1 && curpro.localbytes != tabval2)
  495. error("inconsistency in number of bytes for locals");
  496. curpro.localbytes = tabval2;
  497. break;
  498. }
  499. process();
  500. curpro.symbol = (sym_p) 0;
  501. if (prodepth==1) {
  502. prodepth=0;
  503. #ifdef PSEUBETWEEN
  504. pcount=0;
  505. #endif
  506. return(0);
  507. } else
  508. return(1);
  509. }
  510. lnp->l_instr = n;
  511. lnp->l_next = curpro.lastline;
  512. curpro.lastline = lnp;
  513. return(0);
  514. }
  515. void tstinpro()
  516. {
  517. if (prodepth==0)
  518. error("This is not allowed outside a procedure");
  519. }