ic_lib.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. /* I N T E R M E D I A T E C O D E
  7. *
  8. * I C _ L I B . C
  9. */
  10. #include <stdio.h>
  11. #include <em_spec.h>
  12. #include <em_pseu.h>
  13. #include <em_mes.h>
  14. #include <arch.h>
  15. #include "../share/types.h"
  16. #include "../share/debug.h"
  17. #include "ic.h"
  18. #include "ic_lookup.h"
  19. #include "ic_io.h"
  20. #include "../share/global.h"
  21. #include "../share/files.h"
  22. #include "ic_lib.h"
  23. STATIC skip_string(n)
  24. offset n;
  25. {
  26. /* Read a string of length n and void it */
  27. while (n--) {
  28. readchar();
  29. }
  30. }
  31. STATIC skip_arguments()
  32. {
  33. /* Skip the arguments of a MES pseudo. The argument
  34. * list is terminated by a sp_cend byte.
  35. */
  36. for (;;) {
  37. switch(table2()) {
  38. case sp_scon:
  39. get_off(); /* void */
  40. /* fall through !!! */
  41. case sp_icon:
  42. case sp_ucon:
  43. case sp_fcon:
  44. get_int(); /* void */
  45. skip_string(get_off());
  46. break;
  47. case sp_cend:
  48. return;
  49. default:
  50. break;
  51. }
  52. }
  53. }
  54. STATIC bool proc_wanted(name)
  55. char *name;
  56. {
  57. /* See if 'name' is the name of an external procedure
  58. * that has been used before, but for which no body
  59. * has been given so far.
  60. */
  61. proc_p p;
  62. if (( p = proclookup(name,IMPORTING)) != (proc_p) 0 &&
  63. !(p->p_flags1 & PF_BODYSEEN)) {
  64. return TRUE;
  65. } else {
  66. return FALSE;
  67. }
  68. }
  69. STATIC bool data_wanted(name)
  70. char *name;
  71. {
  72. /* See if 'name' is the name of an externally visible
  73. * data block that has been used before, but for which
  74. * no defining occurrence has been given yet.
  75. */
  76. dblock_p db;
  77. if ((db = symlookup(name,IMPORTING)) != (dblock_p) 0 &&
  78. db->d_pseudo == DUNKNOWN) {
  79. return TRUE;
  80. } else {
  81. return FALSE;
  82. }
  83. }
  84. STATIC bool wanted_names()
  85. {
  86. /* Read the names of procedures and data labels,
  87. * appearing in a 'MES ms_ext' pseudo. Those are
  88. * the names of entities that are imported by
  89. * a library module.
  90. * If any of them is wanted, return TRUE.
  91. * A name is wanted if it is the name of a procedure
  92. * or data block for which applied occurrences but
  93. * no defining occurrence has been met.
  94. */
  95. for (;;) {
  96. switch(table2()) {
  97. case DLBX:
  98. if (data_wanted(string)) {
  99. return TRUE;
  100. }
  101. /* A data entity with the name
  102. * string is available.
  103. */
  104. break;
  105. case sp_pnam:
  106. if (proc_wanted(string)) {
  107. return TRUE;
  108. }
  109. break;
  110. case sp_cend:
  111. return FALSE;
  112. default:
  113. error("wrong argument of MES %d", ms_ext);
  114. }
  115. }
  116. }
  117. STATIC FILE *curfile = NULL;
  118. STATIC bool useful()
  119. {
  120. /* Determine if any entity imported by the current
  121. * compact EM assembly file (which will usually be
  122. * part of an archive file) is useful to us.
  123. * The file must contain (before any other non-MES line)
  124. * a 'MES ms_ext' pseudo that has as arguments the names
  125. * of the entities imported.
  126. */
  127. for (;;) {
  128. if (table1() != PSEU || tabval != ps_mes) {
  129. error("cannot find MES %d in library file",ms_ext);
  130. }
  131. if (table2() != CSTX1) {
  132. error("message number expected");
  133. }
  134. if (tabval == ms_ext) {
  135. /* This is the one we searched */
  136. return wanted_names();
  137. /* Read the names of the imported entities
  138. * and check if any of them is wanted.
  139. */
  140. } else {
  141. skip_arguments(); /* skip remainder of this MES */
  142. }
  143. }
  144. }
  145. STATIC bool is_archive(name)
  146. char *name;
  147. {
  148. /* See if 'name' is the name of an archive file, i.e. it
  149. * should end on ".ma" and should at least be four characters
  150. * long (i.e. the name ".ma" is not accepted as an archive name!).
  151. */
  152. register char *p;
  153. for (p = name; *p; p++);
  154. return (p > name+3) && (*--p == 'a') && (*--p == 'm') && (*--p == '.');
  155. }
  156. STATIC struct ar_hdr hdr;
  157. STATIC bool read_hdr()
  158. {
  159. /* Read the header of an archive module */
  160. char buf[AR_TOTAL];
  161. register char *c = buf;
  162. register char *p = hdr.ar_name;
  163. register int i;
  164. fread(c, AR_TOTAL, 1, curfile);
  165. if (feof(curfile)) return 0;
  166. i = 14;
  167. while (i--) {
  168. *p++ = *c++;
  169. }
  170. #define get2(c) (((c)[0]&0377) | ((unsigned) ((c)[1]&0377) << 8))
  171. hdr.ar_date = ((long) get2(c)) << 16; c += 2;
  172. hdr.ar_date |= ((long) get2(c)) & 0xffff; c += 2;
  173. hdr.ar_uid = *c++;
  174. hdr.ar_gid = *c++;
  175. hdr.ar_mode = get2(c); c += 2;
  176. hdr.ar_size = (long) get2(c) << 16; c += 2;
  177. hdr.ar_size |= (long) get2(c) & 0xffff;
  178. return 1;
  179. }
  180. STATIC int argcnt = ARGSTART - 1;
  181. STATIC short arstate = NO_ARCHIVE;
  182. FILE *next_file(argc,argv)
  183. int argc;
  184. char *argv[];
  185. {
  186. /* See if there are more EM input files. The file names
  187. * are given via argv. If a file is an archive file
  188. * it is supposed to be a library of EM compact assembly
  189. * files. A module (file) contained in this archive file
  190. * is only used if it imports at least one procedure or
  191. * datalabel for which we have not yet seen a defining
  192. * occurrence, although we have seen a used occurrence.
  193. */
  194. long ptr;
  195. for (;;) {
  196. /* This loop is only exited via a return */
  197. if (arstate == ARCHIVE) {
  198. /* We were reading an archive file */
  199. if (ftell(curfile) & 1) {
  200. /* modules in an archive file always
  201. * begin on a word boundary, i.e. at
  202. * an even address.
  203. */
  204. fseek(curfile,1L,1);
  205. }
  206. if (read_hdr()) { /* read header of next module */
  207. ptr = ftell(curfile); /* file position */
  208. file_init(curfile,ARCHIVE,hdr.ar_size);
  209. /* tell i/o package that we're reading
  210. * an archive module of given length.
  211. */
  212. if (useful()) {
  213. /* re-initialize file, because 'useful'
  214. * has read some bytes too.
  215. */
  216. fseek(curfile,ptr,0); /* start module */
  217. file_init(curfile,ARCHIVE,hdr.ar_size);
  218. return curfile;
  219. } else {
  220. /* skip this module */
  221. fseek(curfile,
  222. ptr+hdr.ar_size,0);
  223. }
  224. } else {
  225. /* done with this archive */
  226. arstate = NO_ARCHIVE;
  227. }
  228. } else {
  229. /* open next file, close old */
  230. if (curfile != NULL) {
  231. fclose(curfile);
  232. }
  233. argcnt++;
  234. if (argcnt >= argc) {
  235. /* done with all arguments */
  236. return NULL;
  237. }
  238. filename = argv[argcnt];
  239. if ((curfile = fopen(filename,"r")) == NULL) {
  240. error("cannot open %s",filename);
  241. }
  242. if (is_archive(filename)) {
  243. /* ends on '.ma' */
  244. arstate = ARCHIVE;
  245. arch_init(curfile); /* read magic ar number */
  246. } else {
  247. file_init(curfile,NO_ARCHIVE,0L);
  248. return curfile;
  249. }
  250. }
  251. }
  252. }