getline.c 11 KB

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