ack/util/ego/ic/ic_lib.c

319 lines
6.3 KiB
C
Raw Permalink Normal View History

1994-06-24 11:31:16 +00:00
/* $Id$ */
1987-03-09 19:15:41 +00:00
/*
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
1984-11-26 13:43:22 +00:00
/* 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>
1991-03-05 12:16:17 +00:00
#include <em_spec.h>
#include <em_pseu.h>
#include <em_mes.h>
#include <arch.h>
1984-11-26 13:43:22 +00:00
#include "../share/types.h"
#include "../share/debug.h"
#include "ic.h"
1984-11-30 10:23:34 +00:00
#include "ic_lookup.h"
1984-11-26 13:43:22 +00:00
#include "ic_io.h"
#include "../share/global.h"
#include "../share/files.h"
#include "ic_lib.h"
STATIC void skip_string(n)
2016-08-21 18:08:05 +00:00
offset n;
1984-11-26 13:43:22 +00:00
{
/* Read a string of length n and void it */
2016-08-21 18:08:05 +00:00
while (n--)
{
1984-11-26 13:43:22 +00:00
readchar();
}
}
STATIC void skip_arguments()
1984-11-26 13:43:22 +00:00
{
/* Skip the arguments of a MES pseudo. The argument
* list is terminated by a sp_cend byte.
*/
2016-08-21 18:08:05 +00:00
for (;;)
{
switch (table2())
{
1984-11-26 13:43:22 +00:00
case sp_scon:
get_off(); /* void */
2016-08-21 18:08:05 +00:00
/* fall through !!! */
1984-11-26 13:43:22 +00:00
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(const char *name)
1984-11-26 13:43:22 +00:00
{
/* 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;
2016-08-21 18:08:05 +00:00
if ((p = proclookup(name, IMPORTING)) != (proc_p)0 && !(p->p_flags1 & PF_BODYSEEN))
{
1984-11-26 13:43:22 +00:00
return TRUE;
2016-08-21 18:08:05 +00:00
}
else
{
1984-11-26 13:43:22 +00:00
return FALSE;
}
}
STATIC bool data_wanted(const char *name)
1984-11-26 13:43:22 +00:00
{
/* 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;
2016-08-21 18:08:05 +00:00
if ((db = symlookup(name, IMPORTING)) != (dblock_p)0 && db->d_pseudo == DUNKNOWN)
{
1984-11-26 13:43:22 +00:00
return TRUE;
2016-08-21 18:08:05 +00:00
}
else
{
1984-11-26 13:43:22 +00:00
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.
*/
2016-08-21 18:08:05 +00:00
for (;;)
{
switch (table2())
{
1984-11-26 13:43:22 +00:00
case DLBX:
2016-08-21 18:08:05 +00:00
if (data_wanted(string))
{
1984-11-26 13:43:22 +00:00
return TRUE;
}
/* A data entity with the name
* string is available.
*/
break;
case sp_pnam:
2016-08-21 18:08:05 +00:00
if (proc_wanted(string))
{
1984-11-26 13:43:22 +00:00
return TRUE;
}
break;
case sp_cend:
return FALSE;
default:
error("wrong argument of MES %d", ms_ext);
}
}
}
2016-08-21 18:08:05 +00:00
STATIC FILE* curfile = NULL;
1984-11-26 13:43:22 +00:00
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.
*/
2016-08-21 18:08:05 +00:00
for (;;)
{
if (table1() != PSEU || tabval != ps_mes)
{
error("cannot find MES %d in library file", ms_ext);
1984-11-26 13:43:22 +00:00
}
2016-08-21 18:08:05 +00:00
if (table2() != CSTX1)
{
1984-11-26 13:43:22 +00:00
error("message number expected");
}
2016-08-21 18:08:05 +00:00
if (tabval == ms_ext)
{
1984-11-26 13:43:22 +00:00
/* This is the one we searched */
return wanted_names();
/* Read the names of the imported entities
* and check if any of them is wanted.
*/
2016-08-21 18:08:05 +00:00
}
else
{
1984-11-26 13:43:22 +00:00
skip_arguments(); /* skip remainder of this MES */
}
}
}
2016-08-21 18:08:05 +00:00
STATIC bool is_archive(name) char* name;
1984-11-26 13:43:22 +00:00
{
/* See if 'name' is the name of an archive file, i.e. it
1989-06-27 15:41:47 +00:00
* should end on ".ma" and should at least be four characters
* long (i.e. the name ".ma" is not accepted as an archive name!).
1984-11-26 13:43:22 +00:00
*/
2016-08-21 18:08:05 +00:00
register char* p;
1984-11-26 13:43:22 +00:00
2016-08-21 18:08:05 +00:00
for (p = name; *p; p++)
;
return (p > name + 3) && (*--p == 'a') && (*--p == 'm') && (*--p == '.');
1984-11-26 13:43:22 +00:00
}
STATIC struct ar_hdr hdr;
STATIC bool read_hdr()
{
/* Read the header of an archive module */
1989-06-27 15:41:47 +00:00
char buf[AR_TOTAL];
2016-08-21 18:08:05 +00:00
register char* c = buf;
register char* p = hdr.ar_name;
1989-06-27 15:41:47 +00:00
register int i;
1984-11-26 13:43:22 +00:00
1989-06-27 15:41:47 +00:00
fread(c, AR_TOTAL, 1, curfile);
2016-08-21 18:08:05 +00:00
if (feof(curfile))
return 0;
1989-06-27 15:41:47 +00:00
i = 14;
2016-08-21 18:08:05 +00:00
while (i--)
{
1989-06-27 15:41:47 +00:00
*p++ = *c++;
}
2016-08-21 18:08:05 +00:00
#define get2(c) (((c)[0] & 0377) | ((unsigned)((c)[1] & 0377) << 8))
1989-06-27 15:41:47 +00:00
2016-08-21 18:08:05 +00:00
hdr.ar_date = ((long)get2(c)) << 16;
c += 2;
hdr.ar_date |= ((long)get2(c)) & 0xffff;
c += 2;
1989-06-27 15:41:47 +00:00
hdr.ar_uid = *c++;
hdr.ar_gid = *c++;
2016-08-21 18:08:05 +00:00
hdr.ar_mode = get2(c);
c += 2;
hdr.ar_size = (long)get2(c) << 16;
c += 2;
hdr.ar_size |= (long)get2(c) & 0xffff;
1989-06-27 15:41:47 +00:00
return 1;
1984-11-26 13:43:22 +00:00
}
STATIC int argcnt = 0;
1984-11-26 13:43:22 +00:00
STATIC short arstate = NO_ARCHIVE;
2016-08-21 18:08:05 +00:00
FILE* next_file(argc, argv) int argc;
char* argv[];
1984-11-26 13:43:22 +00:00
{
/* 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.
*/
2016-08-21 18:08:05 +00:00
long ptr;
1984-11-26 13:43:22 +00:00
2016-08-21 18:08:05 +00:00
for (;;)
{
1984-11-26 13:43:22 +00:00
/* This loop is only exited via a return */
2016-08-21 18:08:05 +00:00
if (arstate == ARCHIVE)
{
1984-11-26 13:43:22 +00:00
/* We were reading an archive file */
2016-08-21 18:08:05 +00:00
if (ftell(curfile) & 1)
{
1984-11-26 13:43:22 +00:00
/* modules in an archive file always
* begin on a word boundary, i.e. at
* an even address.
*/
2016-08-21 18:08:05 +00:00
fseek(curfile, 1L, 1);
1984-11-26 13:43:22 +00:00
}
2016-08-21 18:08:05 +00:00
if (read_hdr())
{ /* read header of next module */
1984-11-26 13:43:22 +00:00
ptr = ftell(curfile); /* file position */
2016-08-21 18:08:05 +00:00
file_init(curfile, ARCHIVE, hdr.ar_size);
1984-11-26 13:43:22 +00:00
/* tell i/o package that we're reading
* an archive module of given length.
*/
2016-08-21 18:08:05 +00:00
if (useful())
{
1984-11-26 13:43:22 +00:00
/* re-initialize file, because 'useful'
* has read some bytes too.
*/
2016-08-21 18:08:05 +00:00
fseek(curfile, ptr, 0); /* start module */
file_init(curfile, ARCHIVE, hdr.ar_size);
1984-11-26 13:43:22 +00:00
return curfile;
2016-08-21 18:08:05 +00:00
}
else
{
1984-11-26 13:43:22 +00:00
/* skip this module */
fseek(curfile,
2016-08-21 18:08:05 +00:00
ptr + hdr.ar_size, 0);
1984-11-26 13:43:22 +00:00
}
2016-08-21 18:08:05 +00:00
}
else
{
1984-11-26 13:43:22 +00:00
/* done with this archive */
arstate = NO_ARCHIVE;
}
2016-08-21 18:08:05 +00:00
}
else
{
1984-11-26 13:43:22 +00:00
/* open next file, close old */
2016-08-21 18:08:05 +00:00
if (curfile != NULL)
{
1984-11-26 13:43:22 +00:00
fclose(curfile);
}
argcnt++;
2016-08-21 18:08:05 +00:00
if (argcnt >= argc)
{
1984-11-26 13:43:22 +00:00
/* done with all arguments */
return NULL;
}
filename = argv[argcnt];
if ((curfile = fopen(filename, "rb")) == NULL)
2016-08-21 18:08:05 +00:00
{
error("cannot open %s", filename);
1984-11-26 13:43:22 +00:00
}
2016-08-21 18:08:05 +00:00
if (is_archive(filename))
{
1989-06-27 15:41:47 +00:00
/* ends on '.ma' */
1984-11-26 13:43:22 +00:00
arstate = ARCHIVE;
arch_init(curfile); /* read magic ar number */
2016-08-21 18:08:05 +00:00
}
else
{
file_init(curfile, NO_ARCHIVE, 0L);
1984-11-26 13:43:22 +00:00
return curfile;
}
}
}
}