encode.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761
  1. /*
  2. * (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. *
  4. * This product is part of the Amsterdam Compiler Kit.
  5. *
  6. * Permission to use, sell, duplicate or disclose this software must be
  7. * obtained in writing. Requests for such permissions may be sent to
  8. *
  9. * Dr. Andrew S. Tanenbaum
  10. * Wiskundig Seminarium
  11. * Vrije Universiteit
  12. * Postbox 7161
  13. * 1007 MC Amsterdam
  14. * The Netherlands
  15. *
  16. */
  17. #ifndef NORCSID
  18. static char rcsid[] = "$Header$";
  19. #endif
  20. /*
  21. * Encode to compact EM assembly language
  22. *
  23. * Author: Johan Stevenson, Vrije Universiteit, Amsterdam
  24. */
  25. #include <stdio.h>
  26. #include <ctype.h>
  27. #include <assert.h>
  28. #include <setjmp.h>
  29. #include <em_spec.h>
  30. #include <em_pseu.h>
  31. #include <em_flag.h>
  32. #include <em_ptyp.h>
  33. #include <em_mes.h>
  34. #define put8(x) putchar(x)
  35. #define check(x) if (!(x)) fail_check()
  36. #define fit16i(x) ((x) >= 0xFFFF8000 && (x) <= 0x00007FFF)
  37. #define fit8u(x) ((x) >= 0 && (x) <= 0xFF)
  38. #define MAXSTR 256
  39. #define HSIZE 256
  40. #define EMPTY (EOF-1)
  41. /*
  42. * global variables
  43. */
  44. int opcode;
  45. int offtyp;
  46. long argval;
  47. int dlbval;
  48. char string[MAXSTR];
  49. int strsiz;
  50. int wsize;
  51. int psize;
  52. int lineno;
  53. int argnum;
  54. int errors;
  55. char *progname;
  56. char *filename = "INPUT";
  57. long wordmask[] = { /* allowed bits in a word */
  58. 0x00000000,
  59. 0x000000FF,
  60. 0x0000FFFF,
  61. 0x00000000,
  62. 0xFFFFFFFF
  63. };
  64. long sizemask[] = { /* allowed bits in multiples of 'wsize' */
  65. 0x00000000,
  66. 0x7FFFFFFF,
  67. 0x7FFFFFFE,
  68. 0x00000000,
  69. 0x7FFFFFFC
  70. };
  71. int peekc = EMPTY;
  72. int hashtab[HSIZE];
  73. jmp_buf recover;
  74. /*
  75. * external tables
  76. */
  77. extern char em_flag[];
  78. extern short em_ptyp[];
  79. extern char em_mnem[][4];
  80. extern char em_pseu[][4];
  81. int main(argc,argv) char **argv; {
  82. progname = argv[0];
  83. if (argc >= 2) {
  84. filename = argv[1];
  85. if (freopen(filename,"r",stdin) == NULL)
  86. fatal("can't open %s",filename);
  87. }
  88. if (argc >= 3)
  89. if (freopen(argv[2],"w",stdout) == NULL)
  90. fatal("can't create %s",argv[2]);
  91. init();
  92. put16(sp_magic);
  93. setjmp(recover);
  94. while (nextline())
  95. ;
  96. return(errors ? -1 : 0);
  97. }
  98. /* ----- copy ----- */
  99. int nextline() {
  100. register c,i;
  101. lineno++;
  102. argnum = 1;
  103. c = nextchar();
  104. if (c == EOF)
  105. return(0);
  106. if (isspace(c) && c != '\n') {
  107. c = nospace();
  108. if (isalpha(c)) {
  109. inmnem(c);
  110. if (opcode <= sp_lmnem)
  111. instr();
  112. else
  113. pseudo();
  114. } else
  115. peekc = c;
  116. } else if (c == '#') {
  117. line_line();
  118. } else {
  119. peekc = c;
  120. i = gettyp(sym_ptyp | ptyp(sp_cst2) | ptyp(sp_cend));
  121. switch (i) {
  122. case sp_cst2:
  123. i = (int) argval;
  124. if (i >= 0 && i < sp_nilb0)
  125. put8(i + sp_filb0);
  126. else
  127. putarg(sp_ilb2);
  128. break;
  129. case sp_dlb2:
  130. case sp_dnam:
  131. putarg(i);
  132. break;
  133. case sp_cend:
  134. break;
  135. }
  136. }
  137. if (nospace() != '\n')
  138. syntax("end of line expected");
  139. return(1);
  140. }
  141. instr() {
  142. register i,j,t;
  143. register long l;
  144. i = opcode;
  145. put8(i);
  146. i -= sp_fmnem;
  147. j = em_flag[i] & EM_PAR;
  148. if (j == PAR_NO)
  149. return;
  150. t = em_ptyp[j];
  151. if (j == PAR_B)
  152. t = ptyp(sp_ilb2);
  153. t = getarg(t);
  154. /*
  155. * range checking
  156. */
  157. switch (j) {
  158. case PAR_N:
  159. check(argval >= 0);
  160. break;
  161. case PAR_G:
  162. if (t != sp_cst2 && t != sp_cst4)
  163. break;
  164. check(argval >= 0);
  165. /* fall through */
  166. case PAR_L:
  167. l = argval >= 0 ? argval : -argval;
  168. check((l & ~wordmask[psize]) == 0);
  169. break;
  170. case PAR_W:
  171. if (t == sp_cend)
  172. break;
  173. check((argval & ~wordmask[wsize]) == 0);
  174. /* fall through */
  175. case PAR_S:
  176. check(argval != 0);
  177. /* fall through */
  178. case PAR_Z:
  179. check((argval & ~sizemask[wsize]) == 0);
  180. break;
  181. case PAR_O:
  182. check(argval != 0);
  183. check((argval & ~sizemask[wsize])==0 || (wsize % argval)==0);
  184. break;
  185. case PAR_B:
  186. t = sp_cst2;
  187. break;
  188. case PAR_R:
  189. check(argval >= 0 && argval <= 2);
  190. break;
  191. }
  192. putarg(t);
  193. }
  194. pseudo() {
  195. register i,t;
  196. i = opcode;
  197. put8(i);
  198. switch (i) {
  199. case ps_bss:
  200. case ps_hol:
  201. putarg(getarg(cst_ptyp));
  202. putarg(getarg(val_ptyp));
  203. putarg(getarg(ptyp(sp_cst2)));
  204. check(argval==0 || argval==1);
  205. break;
  206. case ps_rom:
  207. case ps_con:
  208. putarg(getarg(val_ptyp));
  209. do
  210. putarg(t = getarg(any_ptyp));
  211. while (t != sp_cend);
  212. break;
  213. case ps_mes:
  214. putarg(getarg(ptyp(sp_cst2)));
  215. if (argval == ms_emx) {
  216. putarg(getarg(ptyp(sp_cst2)));
  217. check(argval > 0 && argval <= 4);
  218. wsize = (int) argval;
  219. putarg(getarg(ptyp(sp_cst2)));
  220. check(argval > 0 && argval <= 4);
  221. psize = (int) argval;
  222. }
  223. do
  224. putarg(t = getarg(any_ptyp));
  225. while (t != sp_cend);
  226. break;
  227. case ps_exa:
  228. case ps_ina:
  229. putarg(getarg(sym_ptyp));
  230. break;
  231. case ps_exp:
  232. case ps_inp:
  233. putarg(getarg(ptyp(sp_pnam)));
  234. break;
  235. case ps_exc:
  236. putarg(getarg(ptyp(sp_cst2)));
  237. putarg(getarg(ptyp(sp_cst2)));
  238. break;
  239. case ps_pro:
  240. putarg(getarg(ptyp(sp_pnam)));
  241. putarg(getarg(cst_ptyp|ptyp(sp_cend)));
  242. break;
  243. case ps_end:
  244. putarg(getarg(cst_ptyp|ptyp(sp_cend)));
  245. break;
  246. default:
  247. syntax("bad pseudo %d",i);
  248. }
  249. }
  250. /* ----- input ----- */
  251. int getarg(typset) {
  252. register c;
  253. if (argnum != 1) {
  254. c = nospace();
  255. if (c != ',') {
  256. if (c != '\n')
  257. syntax("comma expected");
  258. peekc = c;
  259. }
  260. }
  261. argnum++;
  262. return(gettyp(typset));
  263. }
  264. int gettyp(typset) {
  265. register c,t,sp;
  266. c = nospace();
  267. if (c == '\n') {
  268. peekc = c;
  269. sp = sp_cend;
  270. } else if (isdigit(c) || c == '+' || c == '-' || c == '(') {
  271. sp = inexpr1(c);
  272. if (sp == sp_cst4 && fit16i(argval))
  273. sp = sp_cst2;
  274. } else if (isalpha(c)) {
  275. inname(c);
  276. sp = offsetted(sp_dnam);
  277. } else if (c == '.') {
  278. in15u();
  279. dlbval = (int) argval;
  280. sp = offsetted(sp_dlb2);
  281. } else if (c == '*') {
  282. in15u();
  283. sp = sp_ilb2;
  284. } else if (c == '$') {
  285. inname(nextchar());
  286. sp = sp_pnam;
  287. } else if (c == '"' || c == '\'') {
  288. sp = instring(c);
  289. } else if (c == '?') {
  290. sp = sp_cend;
  291. } else
  292. syntax("operand expected");
  293. t = sp - sp_fspec;
  294. assert(t >= 0 && t < 16);
  295. t = 1 << t;
  296. if ((typset & t) == 0)
  297. error("bad argument type %d",sp);
  298. return(sp);
  299. }
  300. int offsetted(sp) {
  301. register c;
  302. c = nospace();
  303. if (c == '+' || c == '-') {
  304. gettyp(cst_ptyp);
  305. if (c == '-')
  306. argval = -argval;
  307. offtyp = sp;
  308. return(sp_doff);
  309. }
  310. peekc = c;
  311. return(sp);
  312. }
  313. inname(c) register c; {
  314. register char *p;
  315. if (isalpha(c) == 0)
  316. syntax("letter expected");
  317. p = string;
  318. do {
  319. if (p < &string[MAXSTR-1])
  320. *p++ = c;
  321. c = nextchar();
  322. } while (isalnum(c));
  323. peekc = c;
  324. *p = '\0';
  325. strsiz = p - string;
  326. }
  327. int inmnem(c) register c; {
  328. register unsigned h;
  329. register i;
  330. inname(c);
  331. h = hash(string);
  332. for (;;) {
  333. h++;
  334. h %= HSIZE;
  335. i = hashtab[h];
  336. if (i == 0)
  337. syntax("bad mnemonic");
  338. if (i <= sp_lmnem) {
  339. assert(i >= sp_fmnem);
  340. if (strcmp(string,em_mnem[i - sp_fmnem]) != 0)
  341. continue;
  342. return(opcode = i);
  343. }
  344. assert(i <= sp_lpseu && i >= sp_fpseu);
  345. if (strcmp(string,em_pseu[i - sp_fpseu]) != 0)
  346. continue;
  347. return(opcode = i);
  348. }
  349. }
  350. int inexpr1(c) register c; {
  351. long left;
  352. if ((c = inexpr2(c)) != sp_cst4)
  353. return(c);
  354. for (;;) {
  355. c = nospace();
  356. if (c != '+' && c != '-') {
  357. peekc = c;
  358. break;
  359. }
  360. left = argval;
  361. if (inexpr2(nospace()) != sp_cst4)
  362. syntax("term expected");
  363. if (c == '+')
  364. argval += left;
  365. else
  366. argval = left - argval;
  367. }
  368. return(sp_cst4);
  369. }
  370. int inexpr2(c) register c; {
  371. long left;
  372. if ((c = inexpr3(c)) != sp_cst4)
  373. return(c);
  374. for (;;) {
  375. c = nospace();
  376. if (c != '*' && c != '/' && c != '%') {
  377. peekc = c;
  378. break;
  379. }
  380. left = argval;
  381. if (inexpr3(nospace()) != sp_cst4)
  382. syntax("factor expected");
  383. if (c == '*')
  384. argval *= left;
  385. else if (c == '/')
  386. argval = left / argval;
  387. else
  388. argval = left % argval;
  389. }
  390. return(sp_cst4);
  391. }
  392. inexpr3(c) register c; {
  393. if (c == '(') {
  394. if (inexpr1(nospace()) != sp_cst4)
  395. syntax("expression expected");
  396. if (nospace() != ')')
  397. syntax("')' expected");
  398. return(sp_cst4);
  399. }
  400. return(innumber(c));
  401. }
  402. int innumber(c) register c; {
  403. register char *p;
  404. register n;
  405. int expsign;
  406. static char numstr[MAXSTR];
  407. long atol();
  408. p = numstr;
  409. expsign = 0;
  410. if (c == '+' || c == '-') {
  411. if (c == '-')
  412. *p++ = c;
  413. c = nextchar();
  414. }
  415. if (isdigit(c) == 0)
  416. syntax("digit expected");
  417. n = sp_cst4;
  418. for (;;) {
  419. if (p >= &numstr[MAXSTR-1])
  420. fatal("number too long");
  421. *p++ = c;
  422. c = nextchar();
  423. if (c == '.' || c == 'e' || c == 'E') {
  424. expsign = c != '.';
  425. n = sp_fcon;
  426. continue;
  427. }
  428. if (expsign) {
  429. expsign = 0;
  430. if (c == '+' || c == '-')
  431. continue;
  432. }
  433. if (isdigit(c) == 0)
  434. break;
  435. }
  436. peekc = c;
  437. *p = '\0';
  438. c = nospace();
  439. if (n == sp_fcon && c != 'F')
  440. syntax("'F' expected");
  441. if (c == 'I' || c == 'U' || c == 'F')
  442. return(incon(numstr,c));
  443. peekc = c;
  444. argval = atol(numstr);
  445. return(sp_cst4);
  446. }
  447. in15u() {
  448. if (innumber(nextchar()) != sp_cst4)
  449. syntax("integer expected");
  450. check((argval & ~077777) == 0);
  451. }
  452. int incon(p,c) register char *p; {
  453. register char *q;
  454. q = string;
  455. while (*q++ = *p++)
  456. ;
  457. strsiz = q - string - 1;
  458. gettyp(cst_ptyp);
  459. return(c == 'I' ? sp_icon : (c == 'U' ? sp_ucon : sp_fcon));
  460. }
  461. int instring(termc) {
  462. register char *p;
  463. register c;
  464. p = string;
  465. for (;;) {
  466. c = nextchar();
  467. if (c == '\n' || c == EOF) {
  468. peekc = c;
  469. syntax("non-terminated string");
  470. }
  471. if (c == termc) {
  472. if (termc == '"')
  473. *p++ = '\0';
  474. break;
  475. }
  476. if (c == '\\')
  477. c = inescape();
  478. if (p >= &string[MAXSTR-1])
  479. fatal("string too long");
  480. *p++ = c;
  481. }
  482. strsiz = p - string;
  483. return(sp_scon);
  484. }
  485. int inescape() {
  486. register c,j,r;
  487. c = nextchar();
  488. if (c >= '0' && c <= '7') {
  489. r = c - '0';
  490. for (j = 0; j < 2; j++) {
  491. c = nextchar();
  492. if (c < '0' || c > '7') {
  493. peekc = c;
  494. return(r);
  495. }
  496. r <<= 3;
  497. r += (c - '0');
  498. }
  499. return(r);
  500. }
  501. switch (c) {
  502. case 'b': return('\b');
  503. case 'f': return('\f');
  504. case 'n': return('\n');
  505. case 'r': return('\r');
  506. case 't': return('\t');
  507. }
  508. return(c);
  509. }
  510. int nospace() {
  511. register c;
  512. do
  513. c = nextchar();
  514. while (isspace(c) && c != '\n');
  515. if (c == ';')
  516. do
  517. c = nextchar();
  518. while (c != '\n' && c != EOF);
  519. return(c);
  520. }
  521. int nextchar() {
  522. register c;
  523. if (peekc != EMPTY) {
  524. c = peekc;
  525. peekc = EMPTY;
  526. return(c);
  527. }
  528. c = getchar();
  529. if (isascii(c) == 0 && c != EOF)
  530. fatal("non-ascii char");
  531. return(c);
  532. }
  533. line_line() {
  534. register char *p,*q;
  535. static char filebuff[MAXSTR+1];
  536. gettyp(ptyp(sp_cst2));
  537. lineno = (int) (argval-1);
  538. gettyp(ptyp(sp_scon));
  539. p = string;
  540. q = filebuff;
  541. while (--strsiz >= 0)
  542. *q++ = *p++;
  543. *q = '\0';
  544. filename = filebuff;
  545. }
  546. init() {
  547. register i;
  548. for (i = sp_fmnem; i <= sp_lmnem; i++)
  549. pre_hash(i,em_mnem[i - sp_fmnem]);
  550. for (i = sp_fpseu; i <= sp_lpseu; i++)
  551. pre_hash(i,em_pseu[i - sp_fpseu]);
  552. /* treat '_' as letter */
  553. /* In System III the array is called _ctype[] without the trailing '_' */
  554. (_ctype_+1)['_'] = (_ctype_+1)['a'];
  555. }
  556. pre_hash(i,s) char *s; {
  557. register unsigned h;
  558. assert(i != 0);
  559. h = hash(s);
  560. for (;;) {
  561. h++;
  562. h %= HSIZE;
  563. if (hashtab[h] == 0) {
  564. hashtab[h] = i;
  565. return;
  566. }
  567. }
  568. }
  569. int hash(s) register char *s; {
  570. register h;
  571. h = 0;
  572. while (*s) {
  573. h <<= 1;
  574. h += *s++;
  575. }
  576. return(h);
  577. }
  578. /* ----- output ----- */
  579. putarg(sp) register sp; {
  580. register i;
  581. switch (sp) {
  582. case sp_ilb2:
  583. i = (int) argval;
  584. if (fit8u(i)) {
  585. put8(sp_ilb1);
  586. put8(i);
  587. break;
  588. }
  589. put8(sp);
  590. put16(i);
  591. break;
  592. case sp_dlb2:
  593. i = dlbval;
  594. if (fit8u(i)) {
  595. put8(sp_dlb1);
  596. put8(i);
  597. break;
  598. }
  599. put8(sp);
  600. put16(i);
  601. break;
  602. case sp_cst2:
  603. case sp_cst4:
  604. if (fit16i(argval) == 0) {
  605. put8(sp_cst4);
  606. put32(argval);
  607. break;
  608. }
  609. i = (int) argval;
  610. if (i >= -sp_zcst0 && i < sp_ncst0 - sp_zcst0) {
  611. put8(i + sp_zcst0 + sp_fcst0);
  612. break;
  613. }
  614. put8(sp_cst2);
  615. put16(i);
  616. break;
  617. case sp_doff:
  618. put8(sp);
  619. putarg(offtyp);
  620. putarg(sp_cst4);
  621. break;
  622. case sp_dnam:
  623. case sp_pnam:
  624. case sp_scon:
  625. put8(sp);
  626. putstr();
  627. break;
  628. case sp_icon:
  629. case sp_ucon:
  630. case sp_fcon:
  631. put8(sp);
  632. putarg(sp_cst4);
  633. putstr();
  634. break;
  635. case sp_cend:
  636. put8(sp);
  637. break;
  638. }
  639. }
  640. putstr() {
  641. register char *p;
  642. long consiz;
  643. consiz = argval;
  644. argval = strsiz;
  645. putarg(sp_cst4);
  646. argval = consiz;
  647. p = string;
  648. while (--strsiz >= 0)
  649. put8(*p++);
  650. }
  651. put16(w) int w; {
  652. put8(w);
  653. put8(w >> 8);
  654. }
  655. put32(f) long f; {
  656. put16((int) f);
  657. put16((int)(f >> 16));
  658. }
  659. /* ----- error handling ----- */
  660. fail_check() {
  661. error("argument range error");
  662. }
  663. /* VARARGS */
  664. error(s,a1,a2,a3,a4) char *s; {
  665. fprintf(stderr,"%s: line %d: ", filename, lineno);
  666. fprintf(stderr,s,a1,a2,a3,a4);
  667. fprintf(stderr,"\n");
  668. errors++;
  669. }
  670. /* VARARGS */
  671. fatal(s,a1,a2,a3,a4) char *s; {
  672. error(s,a1,a2,a3,a4);
  673. exit(-1);
  674. }
  675. /* VARARGS */
  676. syntax(s,a1,a2,a3,a4) char *s; {
  677. register c;
  678. error(s,a1,a2,a3,a4);
  679. do
  680. c = nextchar();
  681. while (c != '\n' && c != EOF);
  682. longjmp(recover);
  683. }