getline.c 11 KB

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