123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- /* $Id$ */
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /* I N T E R M E D I A T E C O D E
- *
- * I C _ L I B . C
- */
- #include <stdio.h>
- #include <em_spec.h>
- #include <em_pseu.h>
- #include <em_mes.h>
- #include <arch.h>
- #include "../share/types.h"
- #include "../share/debug.h"
- #include "ic.h"
- #include "ic_lookup.h"
- #include "ic_io.h"
- #include "../share/global.h"
- #include "../share/files.h"
- #include "ic_lib.h"
- static void skip_string(offset n)
- {
- /* Read a string of length n and void it */
- while (n--) {
- readchar();
- }
- }
- static void skip_arguments()
- {
- /* Skip the arguments of a MES pseudo. The argument
- * list is terminated by a sp_cend byte.
- */
- for (;;) {
- switch(table2()) {
- case sp_scon:
- get_off(); /* void */
- /* fall through !!! */
- case sp_icon:
- case sp_ucon:
- case sp_fcon:
- get_int(); /* void */
- skip_string(get_off());
- break;
- case sp_cend:
- return;
- default:
- break;
- }
- }
- }
- static bool proc_wanted(char *name)
- {
- /* See if 'name' is the name of an external procedure
- * that has been used before, but for which no body
- * has been given so far.
- */
- proc_p p;
- if (( p = proclookup(name,IMPORTING)) != (proc_p) 0 &&
- !(p->p_flags1 & PF_BODYSEEN)) {
- return TRUE;
- } else {
- return FALSE;
- }
- }
- static bool data_wanted(char *name)
- {
- /* See if 'name' is the name of an externally visible
- * data block that has been used before, but for which
- * no defining occurrence has been given yet.
- */
- dblock_p db;
- if ((db = symlookup(name,IMPORTING)) != (dblock_p) 0 &&
- db->d_pseudo == DUNKNOWN) {
- return TRUE;
- } else {
- return FALSE;
- }
- }
- static bool wanted_names()
- {
- /* Read the names of procedures and data labels,
- * appearing in a 'MES ms_ext' pseudo. Those are
- * the names of entities that are imported by
- * a library module.
- * If any of them is wanted, return TRUE.
- * A name is wanted if it is the name of a procedure
- * or data block for which applied occurrences but
- * no defining occurrence has been met.
- */
- for (;;) {
- switch(table2()) {
- case DLBX:
- if (data_wanted(string)) {
- return TRUE;
- }
- /* A data entity with the name
- * string is available.
- */
- break;
- case sp_pnam:
- if (proc_wanted(string)) {
- return TRUE;
- }
- break;
- case sp_cend:
- return FALSE;
- default:
- error("wrong argument of MES %d", ms_ext);
- }
- }
- }
- static FILE *curfile = NULL;
- static bool useful()
- {
- /* Determine if any entity imported by the current
- * compact EM assembly file (which will usually be
- * part of an archive file) is useful to us.
- * The file must contain (before any other non-MES line)
- * a 'MES ms_ext' pseudo that has as arguments the names
- * of the entities imported.
- */
- for (;;) {
- if (table1() != PSEU || tabval != ps_mes) {
- error("cannot find MES %d in library file",ms_ext);
- }
- if (table2() != CSTX1) {
- error("message number expected");
- }
- if (tabval == ms_ext) {
- /* This is the one we searched */
- return wanted_names();
- /* Read the names of the imported entities
- * and check if any of them is wanted.
- */
- } else {
- skip_arguments(); /* skip remainder of this MES */
- }
- }
- }
- static bool is_archive(char *name)
- {
- /* See if 'name' is the name of an archive file, i.e. it
- * should end on ".ma" and should at least be four characters
- * long (i.e. the name ".ma" is not accepted as an archive name!).
- */
- register char *p;
- for (p = name; *p; p++);
- return (p > name+3) && (*--p == 'a') && (*--p == 'm') && (*--p == '.');
- }
- static struct ar_hdr hdr;
- static bool read_hdr()
- {
- /* Read the header of an archive module */
- char buf[AR_TOTAL];
- register char *c = buf;
- register char *p = hdr.ar_name;
- register int i;
- fread(c, AR_TOTAL, 1, curfile);
- if (feof(curfile)) return 0;
- i = 14;
- while (i--) {
- *p++ = *c++;
- }
- #define get2(c) (((c)[0]&0377) | ((unsigned) ((c)[1]&0377) << 8))
- hdr.ar_date = ((long) get2(c)) << 16; c += 2;
- hdr.ar_date |= ((long) get2(c)) & 0xffff; c += 2;
- hdr.ar_uid = *c++;
- hdr.ar_gid = *c++;
- hdr.ar_mode = get2(c); c += 2;
- hdr.ar_size = (long) get2(c) << 16; c += 2;
- hdr.ar_size |= (long) get2(c) & 0xffff;
- return 1;
- }
- static int argcnt = ARGSTART - 1;
- static short arstate = NO_ARCHIVE;
- FILE *next_file(int argc, char *argv[])
- {
- /* See if there are more EM input files. The file names
- * are given via argv. If a file is an archive file
- * it is supposed to be a library of EM compact assembly
- * files. A module (file) contained in this archive file
- * is only used if it imports at least one procedure or
- * datalabel for which we have not yet seen a defining
- * occurrence, although we have seen a used occurrence.
- */
- long ptr;
- for (;;) {
- /* This loop is only exited via a return */
- if (arstate == ARCHIVE) {
- /* We were reading an archive file */
- if (ftell(curfile) & 1) {
- /* modules in an archive file always
- * begin on a word boundary, i.e. at
- * an even address.
- */
- fseek(curfile,1L,1);
- }
- if (read_hdr()) { /* read header of next module */
- ptr = ftell(curfile); /* file position */
- file_init(curfile,ARCHIVE,hdr.ar_size);
- /* tell i/o package that we're reading
- * an archive module of given length.
- */
- if (useful()) {
- /* re-initialize file, because 'useful'
- * has read some bytes too.
- */
- fseek(curfile,ptr,0); /* start module */
- file_init(curfile,ARCHIVE,hdr.ar_size);
- return curfile;
- } else {
- /* skip this module */
- fseek(curfile,
- ptr+hdr.ar_size,0);
- }
- } else {
- /* done with this archive */
- arstate = NO_ARCHIVE;
- }
- } else {
- /* open next file, close old */
- if (curfile != NULL) {
- fclose(curfile);
- }
- argcnt++;
- if (argcnt >= argc) {
- /* done with all arguments */
- return NULL;
- }
- filename = argv[argcnt];
- if ((curfile = fopen(filename,"r")) == NULL) {
- error("cannot open %s",filename);
- }
- if (is_archive(filename)) {
- /* ends on '.ma' */
- arstate = ARCHIVE;
- arch_init(curfile); /* read magic ar number */
- } else {
- file_init(curfile,NO_ARCHIVE,0L);
- return curfile;
- }
- }
- }
- }
|