getline.c 11 KB

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