123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318 |
- /* $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 skip_string(n)
- offset n;
- {
- /* Read a string of length n and void it */
- while (n--)
- {
- readchar();
- }
- }
- STATIC 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(name) 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(name) 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(name) 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 = 0;
- STATIC short arstate = NO_ARCHIVE;
- FILE* next_file(argc, argv) 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;
- }
- }
- }
- }
|