read_em.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /* $Id$ */
  2. /*
  3. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  4. * See the copyright notice in the ACK home directory, in the file "Copyright".
  5. */
  6. /* Read_em: a module to read either compact or human readable EM code.
  7. Exported are the following routines:
  8. EM_open() : has a parameter representing either a pointer to a
  9. filename or a null pointer, indicating that input is
  10. from standard input. This routine initializes for
  11. reading.
  12. EM_getinstr() : Delivers the next EM instruction in a format
  13. defined in <em_comp.h>.
  14. Imported are:
  15. The constants COMPACT (either defined or not defined) and
  16. CHECKING (again either defined or not defined),
  17. some routines from the system module. and the em_code module
  18. */
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <assert.h>
  22. #include <alloc.h>
  23. #include <system.h>
  24. #include <ctype.h>
  25. #include <em_label.h>
  26. #include <em_arith.h>
  27. #include <em_pseu.h>
  28. #include <em_spec.h>
  29. #include "em_ptyp.h"
  30. #include "em_comp.h"
  31. #include <em_flag.h>
  32. #include <em_mes.h>
  33. /* Buffered input */
  34. #define getbyte() (*_ich ? (*_ich++ & 0377) : _fill())
  35. #define ungetbyte(uch) ((uch) >= 0 && (*--_ich = (uch)))
  36. #define init_input() (_fill(), _ich--)
  37. static File *fd;
  38. static char *_ich;
  39. static int _fill()
  40. {
  41. static char text[BUFSIZ + 1];
  42. static int sz;
  43. if (_ich && _ich < &text[sz]) return _ich++, '\0';
  44. _ich = text;
  45. if (sys_read(fd, text, BUFSIZ, &sz) &&
  46. sz > 0
  47. ) {
  48. text[sz] = '\0';
  49. return (*_ich++&0377);
  50. }
  51. else {
  52. sz = 0;
  53. text[0] = 0;
  54. return EOF;
  55. }
  56. }
  57. static struct e_instr *emhead; /* Where we put the head */
  58. static struct e_instr aheads[3];
  59. static int ahead;
  60. static struct string {
  61. int length;
  62. unsigned int maxlen;
  63. char *str;
  64. } string;
  65. static int state; /* What state are we in? */
  66. #define CON 01 /* Reading a CON */
  67. #define ROM 02 /* Reading a ROM */
  68. #define MES 03 /* Reading a MES */
  69. #define PSEUMASK 03
  70. static int EM_initialized; /* EM_open called? */
  71. long wordmask[] = { /* allowed bits in a word */
  72. 0x00000000,
  73. 0x000000FF,
  74. 0x0000FFFF,
  75. 0x00000000,
  76. 0xFFFFFFFF
  77. };
  78. static int wsize, psize; /* word size and pointer size */
  79. #ifdef CHECKING
  80. static char *argrange = "Argument range error";
  81. #define check(expr) (expr || EM_error || (EM_error = argrange))
  82. #else /* not CHECKING */
  83. #define check(x) /* nothing */
  84. #endif /* CHECKING */
  85. /* Error handling
  86. */
  87. static void xerror(char *s)
  88. {
  89. if (emhead->em_type != EM_FATAL) emhead->em_type = EM_ERROR;
  90. if (!EM_error) EM_error = s;
  91. }
  92. #ifdef COMPACT
  93. void xfatal(char *s)
  94. {
  95. emhead->em_type = EM_FATAL;
  96. if (!EM_error) EM_error = s;
  97. }
  98. #include "readk.c"
  99. #else /* not COMPACT */
  100. #include "reade.c"
  101. #endif /* COMPACT */
  102. /* EM_open: Open input file, get magic word if COMPACT.
  103. */
  104. int EM_open(char *filename)
  105. {
  106. if (EM_initialized) {
  107. EM_error = "EM_open already called";
  108. return 0;
  109. }
  110. if (filename) {
  111. if (!sys_open(filename, OP_READ, &fd)) {
  112. EM_error = "Could not open input file";
  113. return 0;
  114. }
  115. }
  116. else fd = STDIN;
  117. EM_filename = filename;
  118. init_input();
  119. #ifdef COMPACT
  120. if (get16() != sp_magic) {
  121. EM_error = "Illegal magic word";
  122. return 0;
  123. }
  124. #else /* not COMPACT */
  125. inithash(); /* initialize hashtable */
  126. #endif /* COMPACT */
  127. EM_initialized = 1;
  128. return 1;
  129. }
  130. /* EM_close: Close input file
  131. */
  132. void EM_close()
  133. {
  134. if (fd != STDIN) {
  135. sys_close(fd);
  136. fd = STDIN;
  137. }
  138. EM_initialized = 0;
  139. }
  140. /* startmes: handle the start of a message. The only important thing here
  141. is to get the wordsize and pointer size, and remember that they
  142. have already been read, not only to check that they are not specified
  143. again, but also to deliver the arguments on next calls to EM_getinstr.
  144. This is indicated by the variable "argp".
  145. */
  146. static void startmes(struct e_instr *p)
  147. {
  148. getarg(cst_ptyp, &(p->em_arg));
  149. state = MES;
  150. if (p->em_cst == ms_emx) {
  151. p = &aheads[ahead++];
  152. getarg(cst_ptyp, &(p->em_arg));
  153. if (wsize && p->em_cst != wsize && !EM_error) {
  154. EM_error = "Different wordsize in duplicate ms_emx";
  155. }
  156. wsize = p->em_cst;
  157. EM_wordsize = p->em_cst;
  158. p->em_type = EM_MESARG;
  159. p = &aheads[ahead++];
  160. getarg(cst_ptyp, &(p->em_arg));
  161. if (psize && p->em_cst != psize && !EM_error) {
  162. EM_error = "Different pointersize in duplicate ms_emx";
  163. }
  164. psize = p->em_cst;
  165. EM_pointersize = p->em_cst;
  166. p->em_type = EM_MESARG;
  167. }
  168. }
  169. /* EM_getinstr: read an "EM_line"
  170. */
  171. int EM_getinstr(struct e_instr *p)
  172. {
  173. EM_error = 0;
  174. if (ahead) {
  175. register int i;
  176. ahead--;
  177. *p = aheads[0];
  178. for (i = 0; i < ahead; i++) aheads[i] = aheads[i+1];
  179. return 1;
  180. }
  181. emhead = p;
  182. p->em_type = 0;
  183. #ifdef CHECKING
  184. if (!EM_initialized) {
  185. EM_error = "Initialization not done";
  186. p->em_type = EM_FATAL;
  187. return 0;
  188. }
  189. #endif /* CHECKING */
  190. if (!state) { /* All clear, get a new line */
  191. gethead(p);
  192. switch(p->em_type) {
  193. case EM_EOF:
  194. return EM_error == 0;
  195. case EM_MNEM: {
  196. register int i,j;
  197. extern char em_flag[];
  198. extern short em_ptyp[];
  199. j = em_flag[p->em_opcode - sp_fmnem] & EM_PAR;
  200. i = em_ptyp[j];
  201. if (j == PAR_NO) { /* No arguments */
  202. p->em_argtype = 0;
  203. }
  204. #ifndef COMPACT
  205. if (j == PAR_B) i = ptyp(sp_ilb2);
  206. #endif /* COMPACT */
  207. if (j != PAR_NO) getarg(i, &(p->em_arg));
  208. #ifndef COMPACT
  209. if (j == PAR_B) {
  210. p->em_cst = p->em_ilb;
  211. p->em_argtype = cst_ptyp;
  212. }
  213. #endif /* COMPACT */
  214. /* range checking
  215. */
  216. #ifdef CHECKING
  217. if (wsize <= 4 && psize <= 4) switch(j) {
  218. case PAR_B:
  219. check(p->em_cst <= 32767);
  220. /* Fall through */
  221. case PAR_N:
  222. check(p->em_cst >= 0);
  223. break;
  224. case PAR_G:
  225. if (p->em_argtype != cst_ptyp) {
  226. break;
  227. }
  228. check(p->em_cst >= 0);
  229. /* Fall through */
  230. case PAR_F:
  231. /* ??? not in original em_decode or em_encode */
  232. case PAR_L:
  233. { arith m = p->em_cst >= 0 ? p->em_cst :
  234. - p->em_cst;
  235. /* Check that the number fits in a pointer */
  236. check((m & ~wordmask[psize]) == 0);
  237. break;
  238. }
  239. case PAR_W:
  240. if (p->em_argtype == 0) {
  241. p->em_cst = 0;
  242. break;
  243. }
  244. check((p->em_cst & ~wordmask[wsize]) == 0);
  245. /* Fall through */
  246. case PAR_S:
  247. check(p->em_cst > 0);
  248. /* Fall through */
  249. case PAR_Z:
  250. check(p->em_cst >= 0 &&
  251. p->em_cst % wsize == 0);
  252. break;
  253. case PAR_O:
  254. check(p->em_cst > 0 &&
  255. ( p->em_cst % wsize == 0 ||
  256. wsize % p->em_cst == 0));
  257. break;
  258. case PAR_R:
  259. check(p->em_cst >= 0 && p->em_cst <= 2);
  260. break;
  261. }
  262. #endif /* CHECKING */
  263. #ifndef COMPACT
  264. checkeol();
  265. #endif /* COMPACT */
  266. }
  267. break;
  268. case EM_PSEU:
  269. /* handle a pseudo, read possible arguments. CON's and
  270. ROM's are handled especially: Only one argument is
  271. read, and a mark is set that an argument list of
  272. type ROM or CON is in process
  273. */
  274. {
  275. struct e_arg dummy;
  276. switch(p->em_opcode) {
  277. case ps_bss:
  278. case ps_hol:
  279. getarg(cst_ptyp, &dummy);
  280. EM_holsize = dummy.ema_cst;
  281. getarg(par_ptyp, &(p->em_arg));
  282. getarg(cst_ptyp, &dummy);
  283. EM_holinit = dummy.ema_cst;
  284. #ifdef CHECKING
  285. /* Check that the last value is 0 or 1
  286. */
  287. if (EM_holinit != 1 && EM_holinit != 0) {
  288. if (! EM_error)
  289. EM_error="Third argument of hol/bss not 0/1";
  290. }
  291. #endif /* CHECKING */
  292. break;
  293. case ps_exa:
  294. case ps_ina:
  295. getarg(lab_ptyp, &(p->em_arg));
  296. break;
  297. case ps_exp:
  298. case ps_inp:
  299. getarg(pro_ptyp, &(p->em_arg));
  300. break;
  301. case ps_exc:
  302. getarg(cst_ptyp, &dummy);
  303. p->em_exc1 = dummy.ema_cst;
  304. getarg(cst_ptyp, &dummy);
  305. p->em_exc2 = dummy.ema_cst;
  306. break;
  307. case ps_pro:
  308. getarg(pro_ptyp, &(p->em_arg));
  309. getarg(cst_ptyp|ptyp(sp_cend), &dummy);
  310. if (dummy.ema_argtype == 0) {
  311. p->em_nlocals = -1;
  312. }
  313. else p->em_nlocals = dummy.ema_cst;
  314. break;
  315. case ps_end:
  316. getarg(cst_ptyp|ptyp(sp_cend), &(p->em_arg));
  317. break;
  318. case ps_con:
  319. getarg(val_ptyp, &(p->em_arg));
  320. state |= CON;
  321. break;
  322. case ps_rom:
  323. getarg(val_ptyp, &(p->em_arg));
  324. state |= ROM;
  325. break;
  326. default:
  327. xerror("Bad pseudo");
  328. break;
  329. }
  330. }
  331. #ifndef COMPACT
  332. if (p->em_opcode != ps_con && p->em_opcode != ps_rom) {
  333. checkeol();
  334. }
  335. #endif /* COMPACT */
  336. break;
  337. case EM_STARTMES:
  338. startmes(p);
  339. break;
  340. }
  341. if (!wsize && !EM_error) {
  342. wsize = 2;
  343. psize = 2;
  344. EM_error = "EM code should start with mes 2";
  345. }
  346. return EM_error == 0;
  347. }
  348. /* Here, we are in a state reading arguments */
  349. getarg(any_ptyp, &(p->em_arg));
  350. if (EM_error && p->em_type != EM_FATAL) {
  351. return 0;
  352. }
  353. if (p->em_argtype == 0) { /* No more arguments */
  354. #ifndef COMPACT
  355. checkeol();
  356. #endif
  357. if (state == MES) {
  358. state = 0;
  359. p->em_type = EM_ENDMES;
  360. return EM_error == 0;
  361. }
  362. /* Here, we have to get the next instruction */
  363. state = 0;
  364. return EM_getinstr(p);
  365. }
  366. /* Here, there was an argument */
  367. if (state == MES) {
  368. p->em_type = EM_MESARG;
  369. return EM_error == 0;
  370. }
  371. p->em_type = EM_PSEU;
  372. if (state == CON) p->em_opcode = ps_con;
  373. else p->em_opcode = ps_rom;
  374. return EM_error == 0;
  375. }