ic_lib.c 6.2 KB

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