fixup commit for tag 'oct-1'
This commit is contained in:
21
util/.distr
21
util/.distr
@@ -1,21 +0,0 @@
|
||||
LLgen
|
||||
ack
|
||||
amisc
|
||||
arch
|
||||
ass
|
||||
cgg
|
||||
cmisc
|
||||
cpp
|
||||
data
|
||||
ego
|
||||
led
|
||||
misc
|
||||
ncgg
|
||||
opt
|
||||
shf
|
||||
topgen
|
||||
int
|
||||
ceg
|
||||
byacc
|
||||
flex
|
||||
grind
|
||||
@@ -1,7 +0,0 @@
|
||||
READ_ME
|
||||
COPYING
|
||||
lib
|
||||
src
|
||||
Makefile
|
||||
proto.make
|
||||
LLgen.1
|
||||
@@ -1,18 +0,0 @@
|
||||
Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
All rights reserved.
|
||||
|
||||
Permission to use and copy this software and its documentation for research
|
||||
and educational use only is hereby granted, provided that the above copyright
|
||||
notice and this permission notice appear in all copies. No commercial use of
|
||||
any kind is permitted without permission in writing from the copyright owner.
|
||||
|
||||
One way of obtaining such a permission is to obtain the Amsterdam Compiler
|
||||
Kit. LLgen is part of it. The Amsterdam Compiler Kit is available from
|
||||
two companies:
|
||||
|
||||
Transmediair Products & Support B.V. Unipress Software
|
||||
Melkweg 3 2025 Lincoln Highway
|
||||
3721 RG Bilthoven Edison, NJ 08817
|
||||
The Netherlands U.S.A.
|
||||
tel: +31 30 281820 tel: +1 908 287 2100
|
||||
fax: +31 30 292294 fax: +1 908 287 4929
|
||||
@@ -1,118 +0,0 @@
|
||||
.\" $Id$
|
||||
.TH LLGEN 1 "$Revision$"
|
||||
.ad
|
||||
.SH NAME
|
||||
LLgen, an extended LL(1) parser generator
|
||||
.SH SYNOPSIS
|
||||
LLgen [ \-vxwa ] [ \-j[\fInum\fP] ] [ \-l\fInum\fP ] [ \-h\fInum\fP ] file ...
|
||||
.SH DESCRIPTION
|
||||
\fILLgen\fP
|
||||
converts a context-free grammar into a set of
|
||||
functions which form a recursive descent parser with no backtrack.
|
||||
The grammar may be ambiguous;
|
||||
ambiguities can be broken by user specifications.
|
||||
.PP
|
||||
\fILLgen\fP
|
||||
reads each
|
||||
\fIfile\fP
|
||||
in sequence.
|
||||
Together, these files must constitute a context-free grammar.
|
||||
For each file,
|
||||
\fILLgen\fP
|
||||
generates an output file, which must be compiled by the
|
||||
C-compiler.
|
||||
In addition, it generates the files
|
||||
\fILpars.c\fP
|
||||
and
|
||||
\fILpars.h.\fP
|
||||
\fILpars.h\fP
|
||||
contains the
|
||||
\fIdefine\fP
|
||||
statements that associate the
|
||||
\fILLgen\fP-assigned `token-codes' with user declared `token-names'.
|
||||
This allows other source files, for instance the source file
|
||||
containing the lexical analyzer,
|
||||
to access the token-codes by
|
||||
using the token-names.
|
||||
\fILpars.c\fP
|
||||
contains the error recovery routines and tables. It must also
|
||||
be compiled by the C-compiler.
|
||||
.PP
|
||||
\fILLgen\fP
|
||||
will only update those output files that differ from their previous
|
||||
version.
|
||||
This allows
|
||||
\fILLgen\fP
|
||||
to be used with
|
||||
\fImake\fP
|
||||
(1) convieniently.
|
||||
.PP
|
||||
To obtain a working program, the user must also supply a
|
||||
lexical analyzer, as well as
|
||||
\fImain\fP
|
||||
and
|
||||
\fILLmessage\fP,
|
||||
an error reporting routine;
|
||||
\fILex\fP
|
||||
(1) is a useful program for creating lexical analysers usable
|
||||
by
|
||||
\fILLgen\fP.
|
||||
.PP
|
||||
\fILLgen\fP accepts the following flags:
|
||||
.IP \fB\-v\fP
|
||||
create a file called
|
||||
\fILL.output\fP,
|
||||
which contains a description of the conflicts that
|
||||
were not resolved.
|
||||
If the flag is given more than once,
|
||||
\fILLgen\fP
|
||||
will be more "verbose".
|
||||
If it is given three times, a complete description of the
|
||||
grammar will be supplied.
|
||||
.IP \fB\-x\fP
|
||||
the sets that are computed are extended with the nonterminal
|
||||
symbols and these extended sets are also included in the
|
||||
\fILL.output\fP
|
||||
file.
|
||||
.IP \fB\-w\fP
|
||||
no warnings are given.
|
||||
.IP \fB\-a\fP
|
||||
Produce ANSI C function headers and prototypes.
|
||||
.IP \fB\-j\fP[\fInum\fP]
|
||||
when this flag is given, \fILLgen\fP will generate dense switches,
|
||||
so that the compiler can generate a jump table for it. This will only be
|
||||
done for switches that have density between
|
||||
\fIlow_percentage\fP and \fIhigh_percentage\fP, as explained below.
|
||||
Usually, compilers generate a jumptable when the density of the switch
|
||||
is above a certain threshold. When jump tables are to be used more often,
|
||||
\fIhigh_percentage\fP must be set to this threshold, and \fIlow_percentage\fP
|
||||
must be set to a minimum threshold. There is a time-space trade-off here.
|
||||
.I num
|
||||
is the minimum number of cases in a switch for the \fB\-j\fP option to be
|
||||
effective. The default value (if
|
||||
.I num
|
||||
is not given) is 8.
|
||||
.IP \fB\-l\fP\fInum\fP
|
||||
The \fIlow_percentage\fP, as described above. Default value is 10.
|
||||
.IP \fB\-h\fP\fInum\fP
|
||||
The \fIhigh_percentage\fP, as described above. Default value is 30.
|
||||
.SH FILES
|
||||
LL.output verbose output file
|
||||
.br
|
||||
Lpars.c the error recovery routines
|
||||
.br
|
||||
Lpars.h defines for token names
|
||||
.SH "SEE ALSO"
|
||||
\fIlex\fP(1)
|
||||
.br
|
||||
\fImake\fP(1)
|
||||
.br
|
||||
\fILLgen, an Extended LL(1) Parser Generator\fP
|
||||
by C.J.H. Jacobs.
|
||||
.SH DIAGNOSTICS
|
||||
Are intended to be self-explanatory. They are reported
|
||||
on standard error. A more detailed report is found in the
|
||||
\fILL.output\fP
|
||||
file.
|
||||
.SH AUTHOR
|
||||
Ceriel J. H. Jacobs
|
||||
@@ -1,43 +0,0 @@
|
||||
# $Id$
|
||||
INSTALLDIR=/usr/local/bin
|
||||
LIBDIR=/usr/local/lib/LLgen
|
||||
MANDIR=/usr/local/man/man1
|
||||
|
||||
all:
|
||||
cd src; make LIBDIR=$(LIBDIR)
|
||||
|
||||
clean:
|
||||
-cd src; make clean
|
||||
|
||||
install:
|
||||
cd src; make LIBDIR=$(LIBDIR)
|
||||
rm -f $(INSTALLDIR)/LLgen $(LIBDIR)/rec $(LIBDIR)/incl $(MANDIR)/LLgen.1
|
||||
cp src/LLgen $(INSTALLDIR)/LLgen
|
||||
cp lib/rec $(LIBDIR)/rec
|
||||
cp lib/incl $(LIBDIR)/incl
|
||||
cp LLgen.1 $(MANDIR)/LLgen.1
|
||||
|
||||
firstinstall:
|
||||
cd src; make LIBDIR=$(LIBDIR) first
|
||||
rm -f $(INSTALLDIR)/LLgen $(LIBDIR)/rec $(LIBDIR)/incl $(MANDIR)/LLgen.1
|
||||
cp src/LLgen $(INSTALLDIR)/LLgen
|
||||
-mkdir $(LIBDIR)
|
||||
cp lib/rec $(LIBDIR)/rec
|
||||
cp lib/incl $(LIBDIR)/incl
|
||||
cp LLgen.1 $(MANDIR)/LLgen.1
|
||||
|
||||
cmp:
|
||||
cd src; make LIBDIR=$(LIBDIR)
|
||||
-cmp src/LLgen $(INSTALLDIR)/LLgen
|
||||
-cmp lib/rec $(LIBDIR)/rec
|
||||
-cmp lib/incl $(LIBDIR)/incl
|
||||
-cmp LLgen.1 $(MANDIR)/LLgen.1
|
||||
|
||||
distr:
|
||||
cd src; make distr
|
||||
|
||||
opr:
|
||||
make pr | opr
|
||||
|
||||
pr:
|
||||
@cd src; make pr
|
||||
@@ -1,19 +0,0 @@
|
||||
$Id$
|
||||
|
||||
To install LLgen, proceed as follows:
|
||||
|
||||
- create a directory to put the libraryfiles in, f.i.
|
||||
/usr/local/lib/LLgen
|
||||
- cd to the src directory
|
||||
- adapt the file machdep.c, should be easy
|
||||
- adapt the Makefile, changing the options to the C-compiler if
|
||||
necessary.
|
||||
- change back to this directory
|
||||
- edit the Makefile. LIBDIR should be set to the directory for the
|
||||
library files, INSTALLDIR should be set to the directory where LLgen
|
||||
is to be put.
|
||||
- now type
|
||||
make firstinstall
|
||||
- This should do all the work.
|
||||
|
||||
LLgen.1 contains a man-page.
|
||||
@@ -1,2 +0,0 @@
|
||||
incl
|
||||
rec
|
||||
@@ -1,58 +0,0 @@
|
||||
/* $Id$ */
|
||||
#ifdef LL_DEBUG
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#define LL_assert(x) assert(x)
|
||||
#else
|
||||
#define LL_assert(x) /* nothing */
|
||||
#endif
|
||||
|
||||
extern int LLsymb;
|
||||
|
||||
#define LL_SAFE(x) /* Nothing */
|
||||
#define LL_SSCANDONE(x) if (LLsymb != x) LLsafeerror(x)
|
||||
#define LL_SCANDONE(x) if (LLsymb != x) LLerror(x)
|
||||
#define LL_NOSCANDONE(x) LLscan(x)
|
||||
#ifdef LL_FASTER
|
||||
#define LLscan(x) if ((LLsymb = LL_LEXI()) != x) LLerror(x)
|
||||
#endif
|
||||
|
||||
extern unsigned int LLscnt[];
|
||||
extern unsigned int LLtcnt[];
|
||||
extern int LLcsymb;
|
||||
|
||||
#define LLsdecr(d) {LL_assert(LLscnt[d] > 0); LLscnt[d]--;}
|
||||
#define LLtdecr(d) {LL_assert(LLtcnt[d] > 0); LLtcnt[d]--;}
|
||||
#define LLsincr(d) LLscnt[d]++
|
||||
#define LLtincr(d) LLtcnt[d]++
|
||||
|
||||
#if LL_ANSI_C
|
||||
extern int LL_LEXI(void);
|
||||
extern void LLread(void);
|
||||
extern int LLskip(void);
|
||||
extern int LLnext(int);
|
||||
extern void LLerror(int);
|
||||
extern void LLsafeerror(int);
|
||||
extern void LLnewlevel(unsigned int *);
|
||||
extern void LLoldlevel(unsigned int *);
|
||||
#ifndef LL_FASTER
|
||||
extern void LLscan(int);
|
||||
#endif
|
||||
#ifndef LLNOFIRSTS
|
||||
extern int LLfirst(int, int);
|
||||
#endif
|
||||
#else /* not LL_ANSI_C */
|
||||
extern LLread();
|
||||
extern int LLskip();
|
||||
extern int LLnext();
|
||||
extern LLerror();
|
||||
extern LLsafeerror();
|
||||
extern LLnewlevel();
|
||||
extern LLoldlevel();
|
||||
#ifndef LL_FASTER
|
||||
extern LLscan();
|
||||
#endif
|
||||
#ifndef LLNOFIRSTS
|
||||
extern int LLfirst();
|
||||
#endif
|
||||
#endif /* not LL_ANSI_C */
|
||||
@@ -1,319 +0,0 @@
|
||||
/*
|
||||
* Some grammar independent code.
|
||||
* This file is copied into Lpars.c.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char *rcsid = "$Id$";
|
||||
#endif
|
||||
|
||||
unsigned int LLtcnt[LL_NTERMINALS];
|
||||
unsigned int LLscnt[LL_NSETS];
|
||||
int LLcsymb, LLsymb;
|
||||
static int LLlevel;
|
||||
|
||||
#if LL_ANSI_C
|
||||
#define LL_VOIDCST (void)
|
||||
void LLmessage(int);
|
||||
#else
|
||||
#define LL_VOIDCST
|
||||
#endif
|
||||
#ifdef LL_USERHOOK
|
||||
#if LL_ANSI_C
|
||||
static int LLdoskip(int);
|
||||
static int LLuserhook(int, int*);
|
||||
#else
|
||||
static int LLdoskip();
|
||||
static int LLuserhook();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LL_FASTER
|
||||
#if LL_ANSI_C
|
||||
void LLscan(int t)
|
||||
#else
|
||||
LLscan(t)
|
||||
int t;
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* Check if the next symbol is equal to the parameter
|
||||
*/
|
||||
if ((LLsymb = LL_LEXI()) == t) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* If we come here, an error has been detected
|
||||
*/
|
||||
LLerror(t);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LL_ANSI_C
|
||||
void LLread(void) {
|
||||
#else
|
||||
LLread() {
|
||||
#endif
|
||||
for (;;) {
|
||||
if ((LLcsymb = LLindex[(LLsymb = LL_LEXI())]) >= 0) return;
|
||||
LLmessage(0);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#if LL_ANSI_C
|
||||
void LLerror(int t)
|
||||
#else
|
||||
LLerror(t)
|
||||
int t;
|
||||
#endif
|
||||
{
|
||||
register int i;
|
||||
|
||||
if (t == EOFILE && LLsymb <= 0) return;
|
||||
#ifdef LL_NEWMESS
|
||||
if (t == EOFILE) {
|
||||
#ifdef LL_USERHOOK
|
||||
static int lst[] = { EOFILE, 0 };
|
||||
LL_VOIDCST LLuserhook(EOFILE, lst);
|
||||
#endif /* LL_USERHOOK */
|
||||
if (LLsymb != EOFILE && LLsymb > 0) {
|
||||
LLmessage(-1);
|
||||
while ((LLsymb = LL_LEXI()) > 0 && LLsymb != EOFILE)
|
||||
/* nothing */ ;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if ((LLcsymb = LLindex[LLsymb]) < 0) {
|
||||
LLmessage(0);
|
||||
LLread();
|
||||
}
|
||||
i = LLindex[t];
|
||||
LLtcnt[i]++;
|
||||
#ifdef LL_USERHOOK
|
||||
LL_VOIDCST LLdoskip(t);
|
||||
#else
|
||||
LL_VOIDCST LLskip();
|
||||
#endif
|
||||
LLtcnt[i]--;
|
||||
if (LLsymb != t) LLmessage(t);
|
||||
}
|
||||
|
||||
#if LL_ANSI_C
|
||||
void LLsafeerror(int t)
|
||||
#else
|
||||
LLsafeerror(t)
|
||||
int t;
|
||||
#endif
|
||||
{
|
||||
if (t == EOFILE && LLsymb <= 0) return;
|
||||
#ifdef LL_NEWMESS
|
||||
if (t == EOFILE) {
|
||||
#ifdef LL_USERHOOK
|
||||
static int lst[] = { EOFILE, 0 };
|
||||
LL_VOIDCST LLuserhook(EOFILE, lst);
|
||||
#endif /* LL_USERHOOK */
|
||||
if (LLsymb != EOFILE && LLsymb > 0) {
|
||||
LLmessage(-1);
|
||||
while ((LLsymb = LL_LEXI()) > 0 && LLsymb != EOFILE)
|
||||
/* nothing */ ;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
LLmessage(t);
|
||||
}
|
||||
|
||||
#ifndef LLNOFIRSTS
|
||||
#if LL_ANSI_C
|
||||
int LLfirst(int x, int d) {
|
||||
#else
|
||||
int LLfirst(x, d) {
|
||||
#endif
|
||||
register int i;
|
||||
|
||||
return (i = LLindex[x]) >= 0 &&
|
||||
(LLsets[d + (i >> 3)] & (1 << (i & 07)));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LL_ANSI_C
|
||||
int LLnext(int n)
|
||||
#else
|
||||
int LLnext(n)
|
||||
int n;
|
||||
#endif
|
||||
{
|
||||
/* returns: 0 if the current symbol is'nt skipped, and it
|
||||
is'nt a member of "n",
|
||||
1 if we have a new symbol, but it is'nt a member,
|
||||
2 if the current symbol is a member,
|
||||
and 3 if we have a new symbol and it is a member.
|
||||
So, the low order bit indicates wether we have a new symbol,
|
||||
and the next bit indicates wether it is a member of "n".
|
||||
*/
|
||||
|
||||
int retval = 0;
|
||||
|
||||
if (LLskip()) retval = 1;
|
||||
if (n <= 0 && LLsets[(LLcsymb >> 3) - n] & (1 << (LLcsymb & 07))) {
|
||||
retval |= 2;
|
||||
}
|
||||
else if (n > 0 && LLcsymb == LLindex[n]) retval |= 2;
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if LL_ANSI_C
|
||||
int LLskip(void) {
|
||||
#else
|
||||
int LLskip() {
|
||||
#endif
|
||||
/* returns 0 if the current symbol is'nt skipped, and
|
||||
1 if it is, t.i., we have a new symbol
|
||||
*/
|
||||
#ifdef LL_USERHOOK
|
||||
return LLdoskip(0);
|
||||
}
|
||||
|
||||
#if LL_ANSI_C
|
||||
extern void LL_USERHOOK(int, int *);
|
||||
static int LLuserhook(int e, int *list)
|
||||
#else
|
||||
static int LLuserhook(e, list)
|
||||
int e;
|
||||
int *list;
|
||||
#endif
|
||||
{
|
||||
int old = LLsymb;
|
||||
LL_USERHOOK(e, list);
|
||||
LLread();
|
||||
return LLsymb != old;
|
||||
}
|
||||
|
||||
#if LL_ANSI_C
|
||||
static void LLmklist(register int *list)
|
||||
#else
|
||||
static LLmklist(list)
|
||||
register int *list;
|
||||
#endif
|
||||
{
|
||||
char Xset[LL_SSIZE];
|
||||
register char *p;
|
||||
register int i;
|
||||
|
||||
for (p = &Xset[0]; p < &Xset[LL_SSIZE]; ) *p++ = 0;
|
||||
for (i = 0; i < LL_NTERMINALS; i++) {
|
||||
if (LLtcnt[i] != 0) Xset[i >> 3] |= (1 << (i & 07));
|
||||
}
|
||||
for (i = LL_NSETS - 1; i >= 0; i--) if (LLscnt[i] != 0) {
|
||||
register char *q = &LLsets[LL_SSIZE * i];
|
||||
|
||||
p = &Xset[0];
|
||||
while (p < &Xset[LL_SSIZE]) *p++ |= *q++;
|
||||
}
|
||||
for (i = 0; i < LL_NTERMINALS; i++) {
|
||||
if (Xset[i >> 3] & (1 << (i & 07))) {
|
||||
*list++ = LLtok[i];
|
||||
}
|
||||
}
|
||||
*list = 0;
|
||||
}
|
||||
|
||||
#if LL_ANSI_C
|
||||
static int LLdoskip(int e)
|
||||
#else
|
||||
static int LLdoskip(e)
|
||||
int e;
|
||||
#endif
|
||||
{
|
||||
int LLx;
|
||||
int list[LL_NTERMINALS+1];
|
||||
#endif /* LL_USERHOOK */
|
||||
register int i;
|
||||
int retval;
|
||||
int LLi, LLb;
|
||||
|
||||
retval = 0;
|
||||
#ifdef LL_USERHOOK
|
||||
LLmklist(list);
|
||||
LLx = LLuserhook(e, list);
|
||||
if (LLx) retval = 1;
|
||||
#endif /* LL_USERHOOK */
|
||||
for (;;) {
|
||||
if (LLtcnt[LLcsymb] != 0) {
|
||||
#ifdef LL_USERHOOK
|
||||
if (!e || !LLx || LLcsymb == LLindex[e])
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
LLi = LLcsymb >> 3;
|
||||
LLb = 1 << (LLcsymb & 07);
|
||||
for (i = LL_NSETS - 1; i >= 0; i--) {
|
||||
if (LLscnt[i] != 0) {
|
||||
if (LLsets[LL_SSIZE*i+LLi] & LLb) {
|
||||
#ifdef LL_USERHOOK
|
||||
if (!e || !LLx || LLcsymb == LLindex[e])
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef LL_USERHOOK
|
||||
if (LLx) {
|
||||
LLx = LLuserhook(e, list);
|
||||
continue;
|
||||
}
|
||||
#endif /* LL_USERHOOK */
|
||||
LLmessage(0);
|
||||
retval = 1;
|
||||
LLread();
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
#if LL_ANSI_C
|
||||
void LLnewlevel(unsigned int *LLsinfo) {
|
||||
#else
|
||||
LLnewlevel(LLsinfo) unsigned int *LLsinfo; {
|
||||
#endif
|
||||
register int i;
|
||||
|
||||
if (LLlevel++) {
|
||||
LLsinfo[LL_NSETS+LL_NTERMINALS] = (unsigned) LLsymb;
|
||||
LLsinfo[LL_NSETS+LL_NTERMINALS+1] = (unsigned) LLcsymb;
|
||||
for (i = LL_NTERMINALS - 1; i >= 0; i--) {
|
||||
LLsinfo[i] = LLtcnt[i];
|
||||
LLtcnt[i] = 0;
|
||||
}
|
||||
for (i = LL_NSETS - 1; i >= 0; i--) {
|
||||
LLsinfo[LL_NTERMINALS+i] = LLscnt[i];
|
||||
LLscnt[i] = 0;
|
||||
}
|
||||
}
|
||||
LLtincr(0);
|
||||
}
|
||||
|
||||
#if LL_ANSI_C
|
||||
void LLoldlevel(unsigned int *LLsinfo) {
|
||||
#else
|
||||
LLoldlevel(LLsinfo) unsigned int *LLsinfo; {
|
||||
#endif
|
||||
register int i;
|
||||
|
||||
LLtdecr(0);
|
||||
#ifdef LL_DEBUG
|
||||
for (i = 0; i < LL_NTERMINALS; i++) LL_assert(LLtcnt[i] == 0);
|
||||
for (i = 0; i < LL_NSETS; i++) LL_assert(LLscnt[i] == 0);
|
||||
#endif
|
||||
if (--LLlevel) {
|
||||
for (i = LL_NSETS - 1; i >= 0; i--) {
|
||||
LLscnt[i] = LLsinfo[LL_NTERMINALS+i];
|
||||
}
|
||||
for (i = LL_NTERMINALS - 1; i >= 0; i--) {
|
||||
LLtcnt[i] = LLsinfo[i];
|
||||
}
|
||||
LLsymb = (int) LLsinfo[LL_NSETS+LL_NTERMINALS];
|
||||
LLcsymb = (int) LLsinfo[LL_NSETS+LL_NTERMINALS+1];
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
#PARAMS do not remove this line!
|
||||
|
||||
INSTALLDIR=$(TARGET_HOME)/bin
|
||||
LIBDIR=$(TARGET_HOME)/lib/LLgen
|
||||
|
||||
all:
|
||||
cd src; make LIBDIR=$(LIBDIR)
|
||||
|
||||
clean:
|
||||
-cd src; make clean
|
||||
|
||||
install:
|
||||
cd src; make LIBDIR=$(LIBDIR)
|
||||
cp src/LLgen $(INSTALLDIR)/LLgen
|
||||
if [ $(DO_MACHINE_INDEP) = y ] ; \
|
||||
then cp $(SRC_HOME)/util/LLgen/lib/rec $(LIBDIR)/rec ; \
|
||||
cp $(SRC_HOME)/util/LLgen/lib/incl $(LIBDIR)/incl ; \
|
||||
mk_manpage $(SRC_HOME)/util/LLgen/LLgen.1 $(TARGET_HOME) ; \
|
||||
fi
|
||||
|
||||
firstinstall:
|
||||
cd src; make LIBDIR=$(LIBDIR) first
|
||||
cp src/LLgen $(INSTALLDIR)/LLgen
|
||||
if [ $(DO_MACHINE_INDEP) = y ] ; \
|
||||
then if [ -d $(LIBDIR) ] ; then : ; else mkdir $(LIBDIR) ; fi ; \
|
||||
cp $(SRC_HOME)/util/LLgen/lib/rec $(LIBDIR)/rec ; \
|
||||
cp $(SRC_HOME)/util/LLgen/lib/incl $(LIBDIR)/incl ; \
|
||||
mk_manpage $(SRC_HOME)/util/LLgen/LLgen.1 $(TARGET_HOME) ; \
|
||||
fi
|
||||
|
||||
cmp:
|
||||
cd src; make LIBDIR=$(LIBDIR)
|
||||
-cmp src/LLgen $(INSTALLDIR)/LLgen
|
||||
-cmp $(SRC_HOME)/util/LLgen/lib/rec $(LIBDIR)/rec
|
||||
-cmp $(SRC_HOME)/util/LLgen/lib/incl $(LIBDIR)/incl
|
||||
|
||||
distr:
|
||||
cd src; make distr
|
||||
|
||||
opr:
|
||||
make pr | opr
|
||||
|
||||
pr:
|
||||
@cd src; make pr
|
||||
@@ -1,24 +0,0 @@
|
||||
cclass.c
|
||||
cclass.h
|
||||
LLgen.c.dist
|
||||
LLgen.g
|
||||
Lpars.c.dist
|
||||
Lpars.h.dist
|
||||
Makefile
|
||||
proto.make
|
||||
alloc.c
|
||||
check.c
|
||||
compute.c
|
||||
extern.h
|
||||
gencode.c
|
||||
global.c
|
||||
io.h
|
||||
machdep.c
|
||||
main.c
|
||||
name.c
|
||||
reach.c
|
||||
sets.c
|
||||
sets.h
|
||||
tokens.c.dist
|
||||
tokens.g
|
||||
types.h
|
||||
@@ -1,680 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* LLgen.g
|
||||
* Defines the grammar of LLgen.
|
||||
* Some routines that build the internal structure are also included
|
||||
*/
|
||||
|
||||
{
|
||||
# include "types.h"
|
||||
# include "io.h"
|
||||
# include "extern.h"
|
||||
# include "assert.h"
|
||||
# include "cclass.h"
|
||||
|
||||
# ifndef NORCSID
|
||||
static string rcsid = "$Id$";
|
||||
# endif
|
||||
p_mem alloc(), ralloc();
|
||||
string store();
|
||||
p_gram search();
|
||||
long ftell();
|
||||
|
||||
static int nparams; /* parameter count for nonterminals */
|
||||
static int acount; /* count #of global actions */
|
||||
static int order;
|
||||
static p_term t_list;
|
||||
static int t_cnt;
|
||||
static p_gram alt_table;
|
||||
static int n_alts;
|
||||
static int max_alts;
|
||||
#define ALTINCR 32
|
||||
|
||||
static p_gram rule_table;
|
||||
static int n_rules;
|
||||
static int max_rules;
|
||||
#define RULEINCR 32
|
||||
|
||||
/* Here are defined : */
|
||||
STATIC newnorder();
|
||||
STATIC newtorder();
|
||||
STATIC copyact();
|
||||
STATIC mkalt();
|
||||
STATIC mkterm();
|
||||
STATIC p_gram copyrule();
|
||||
/* and of course LLparse() */
|
||||
|
||||
STATIC
|
||||
newnorder(index) {
|
||||
static int porder;
|
||||
|
||||
if (norder != -1) {
|
||||
nonterms[porder].n_next = index;
|
||||
}
|
||||
else norder = index;
|
||||
porder = index;
|
||||
nonterms[porder].n_next = -1;
|
||||
}
|
||||
|
||||
STATIC
|
||||
newtorder(index) {
|
||||
static int porder;
|
||||
|
||||
if (torder != -1) {
|
||||
tokens[porder].t_next = index;
|
||||
}
|
||||
else torder = index;
|
||||
porder = index;
|
||||
tokens[porder].t_next = -1;
|
||||
}
|
||||
|
||||
p_init()
|
||||
{
|
||||
alt_table = (p_gram )alloc(ALTINCR*sizeof(t_gram));
|
||||
n_alts = 0;
|
||||
max_alts = ALTINCR;
|
||||
rule_table = (p_gram )alloc(RULEINCR*sizeof(t_gram));
|
||||
n_rules = 0;
|
||||
max_rules = RULEINCR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
%start LLparse, spec;
|
||||
|
||||
spec : { acount = 0; p_init(); }
|
||||
[ %persistent def ]*
|
||||
{ /*
|
||||
* Put an endmarker in temporary file
|
||||
*/
|
||||
putc('\0', fact);
|
||||
putc('\0', fact);
|
||||
free((p_mem) rule_table);
|
||||
free((p_mem) alt_table);
|
||||
}
|
||||
;
|
||||
|
||||
def { register string p; }
|
||||
: rule
|
||||
/*
|
||||
* A grammar rule
|
||||
*/
|
||||
| C_TOKEN listel [ ',' listel ]* ';'
|
||||
/*
|
||||
* A token declaration
|
||||
*/
|
||||
| C_START C_IDENT
|
||||
{ p = store(lextoken.t_string); }
|
||||
',' C_IDENT ';'
|
||||
/*
|
||||
* A start symbol declaration
|
||||
*/
|
||||
{ /*
|
||||
* Put the declaration in the list
|
||||
* of start symbols
|
||||
*/
|
||||
register p_gram temp;
|
||||
register p_start ff;
|
||||
|
||||
temp = search(NONTERM,lextoken.t_string,BOTH);
|
||||
ff = (p_start) alloc(sizeof(t_start));
|
||||
ff->ff_nont = g_getcont(temp);
|
||||
ff->ff_name = p;
|
||||
ff->ff_next = start;
|
||||
start = ff;
|
||||
while (ff = ff->ff_next) {
|
||||
if (! strcmp(p, ff->ff_name)) {
|
||||
error(linecount, "\"%s\" already used in a %%start", p);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
| C_LEXICAL C_IDENT
|
||||
/*
|
||||
* Declaration of a name for the lexical analyser.
|
||||
* May appear only once
|
||||
*/
|
||||
{ if (!lexical) {
|
||||
lexical = store(lextoken.t_string);
|
||||
}
|
||||
else error(linecount,"Duplicate %%lexical");
|
||||
}
|
||||
';'
|
||||
| C_PREFIX C_IDENT
|
||||
/*
|
||||
* Prefix of external names (default: LL)
|
||||
*/
|
||||
{ if (!prefix) {
|
||||
prefix = store(lextoken.t_string);
|
||||
if (strlen(prefix) > 6) {
|
||||
error(linecount,
|
||||
"%%prefix too long");
|
||||
prefix[6] = 0;
|
||||
}
|
||||
}
|
||||
else error(linecount,"Duplicate %%prefix");
|
||||
}
|
||||
';'
|
||||
| C_ONERROR C_IDENT
|
||||
{ if (! onerror) {
|
||||
onerror = store(lextoken.t_string);
|
||||
}
|
||||
else error(linecount,"Duplicate %%onerror");
|
||||
}
|
||||
';'
|
||||
| action(0) { acount++; }
|
||||
/*
|
||||
* A global C-declaration
|
||||
*/
|
||||
| firsts
|
||||
/*
|
||||
* declarations for macros
|
||||
*/
|
||||
;
|
||||
|
||||
listel : C_IDENT { p_gram temp = search(TERMINAL,lextoken.t_string,ENTERING);
|
||||
newtorder(g_getcont(temp));
|
||||
tokens[g_getcont(temp)].t_lineno = linecount;
|
||||
}
|
||||
;
|
||||
|
||||
rule { register p_nont p;
|
||||
p_gram rr;
|
||||
register p_gram temp;
|
||||
}
|
||||
: /*
|
||||
* grammar for a production rule
|
||||
*/
|
||||
C_IDENT { temp = search(NONTERM,lextoken.t_string,BOTH);
|
||||
p = &nonterms[g_getcont(temp)];
|
||||
if (p->n_rule) {
|
||||
error(linecount,
|
||||
"Nonterminal %s already defined", lextoken.t_string);
|
||||
}
|
||||
/*
|
||||
* Remember the order in which the nonterminals
|
||||
* were defined. Code must be generated in that
|
||||
* order to keep track with the actions on the
|
||||
* temporary file
|
||||
*/
|
||||
newnorder(p - nonterms);
|
||||
p->n_count = acount;
|
||||
acount = 0;
|
||||
p->n_lineno = linecount;
|
||||
p->n_off = ftell(fact);
|
||||
}
|
||||
[ params { if (nparams > 0) {
|
||||
p->n_flags |= PARAMS;
|
||||
if (nparams > 15) {
|
||||
error(linecount,"Too many parameters");
|
||||
}
|
||||
else setntparams(p,nparams);
|
||||
}
|
||||
}
|
||||
]?
|
||||
[ action(0) { p->n_flags |= LOCALS; }
|
||||
]?
|
||||
':' productions(&rr) ';'
|
||||
/*
|
||||
* Do not use p->n_rule now! The nonterms array
|
||||
* might have been re-allocated.
|
||||
*/
|
||||
{ nonterms[g_getcont(temp)].n_rule = rr;}
|
||||
;
|
||||
|
||||
action(int n;)
|
||||
/*
|
||||
* The parameter n is non-zero when the opening and closing
|
||||
* bracket must be copied along with the action
|
||||
*/
|
||||
: '{' { copyact('{','}',n,0); }
|
||||
'}'
|
||||
;
|
||||
|
||||
productions(p_gram *p;)
|
||||
/*
|
||||
* One or more alternatives
|
||||
*/
|
||||
{ p_gram prod;
|
||||
int conflres = 0;
|
||||
int t = 0;
|
||||
int haddefault = 0;
|
||||
int altcnt = 0;
|
||||
int o_lc, n_lc;
|
||||
} :
|
||||
{ o_lc = linecount; }
|
||||
simpleproduction(p,&conflres)
|
||||
{ if (conflres & DEF) haddefault = 1; }
|
||||
[
|
||||
[ '|' { n_lc = linecount; }
|
||||
simpleproduction(&prod,&t)
|
||||
{ if (n_alts >= max_alts-2) {
|
||||
alt_table = (p_gram ) ralloc(
|
||||
(p_mem) alt_table,
|
||||
(unsigned)(max_alts+=ALTINCR)*sizeof(t_gram));
|
||||
}
|
||||
if (t & DEF) {
|
||||
if (haddefault) {
|
||||
error(n_lc,
|
||||
"More than one %%default in alternation");
|
||||
}
|
||||
haddefault = 1;
|
||||
}
|
||||
mkalt(*p,conflres,o_lc,&alt_table[n_alts++]);
|
||||
altcnt++;
|
||||
o_lc = n_lc;
|
||||
conflres = t;
|
||||
t = 0;
|
||||
*p = prod;
|
||||
}
|
||||
]+ { if (conflres & ~DEF) {
|
||||
error(n_lc,
|
||||
"Resolver on last alternative not allowed");
|
||||
}
|
||||
mkalt(*p,conflres,n_lc,&alt_table[n_alts++]);
|
||||
altcnt++;
|
||||
g_settype((&alt_table[n_alts]),EORULE);
|
||||
*p = copyrule(&alt_table[n_alts-altcnt],altcnt+1);
|
||||
}
|
||||
|
|
||||
{ if (conflres & ~DEF) {
|
||||
error(o_lc,
|
||||
"No alternation conflict resolver allowed here");
|
||||
}
|
||||
/*
|
||||
if (conflres & DEF) {
|
||||
error(o_lc,
|
||||
"No %%default allowed here");
|
||||
}
|
||||
*/
|
||||
}
|
||||
]
|
||||
{ n_alts -= altcnt; }
|
||||
;
|
||||
{
|
||||
|
||||
STATIC
|
||||
mkalt(prod,condition,lc,res) p_gram prod; register p_gram res; {
|
||||
/*
|
||||
* Create an alternation and initialise it.
|
||||
*/
|
||||
register p_link l;
|
||||
static p_link list;
|
||||
static int cnt;
|
||||
|
||||
if (! cnt) {
|
||||
cnt = 50;
|
||||
list = (p_link) alloc(50 * sizeof(t_link));
|
||||
}
|
||||
cnt--;
|
||||
l = list++;
|
||||
l->l_rule = prod;
|
||||
l->l_flag = condition;
|
||||
g_setlink(res,l);
|
||||
g_settype(res,ALTERNATION);
|
||||
res->g_lineno = lc;
|
||||
nalts++;
|
||||
}
|
||||
}
|
||||
|
||||
simpleproduction(p_gram *p; register int *conflres;)
|
||||
{ t_gram elem;
|
||||
int elmcnt = 0;
|
||||
int cnt, kind;
|
||||
int termdeleted = 0;
|
||||
} :
|
||||
[ C_DEFAULT { *conflres = DEF; }
|
||||
]?
|
||||
[
|
||||
/*
|
||||
* Optional conflict reslover
|
||||
*/
|
||||
C_IF expr { *conflres |= COND; }
|
||||
| C_PREFER { *conflres |= PREFERING; }
|
||||
| C_AVOID { *conflres |= AVOIDING; }
|
||||
]?
|
||||
[ %persistent elem(&elem)
|
||||
{ if (n_rules >= max_rules-2) {
|
||||
rule_table = (p_gram) ralloc(
|
||||
(p_mem) rule_table,
|
||||
(unsigned)(max_rules+=RULEINCR)*sizeof(t_gram));
|
||||
}
|
||||
kind = FIXED;
|
||||
cnt = 0;
|
||||
}
|
||||
[ repeats(&kind, &cnt)
|
||||
{ if (g_gettype(&elem) != TERM) {
|
||||
rule_table[n_rules] = elem;
|
||||
g_settype((&rule_table[n_rules+1]),EORULE);
|
||||
mkterm(copyrule(&rule_table[n_rules],2),
|
||||
0,
|
||||
elem.g_lineno,
|
||||
&elem);
|
||||
}
|
||||
}
|
||||
|
|
||||
{ if (g_gettype(&elem) == TERM) {
|
||||
register p_term q = g_getterm(&elem);
|
||||
|
||||
if (! (q->t_flags & RESOLVER) &&
|
||||
g_gettype(q->t_rule) != ALTERNATION &&
|
||||
g_gettype(q->t_rule) != EORULE) {
|
||||
while (g_gettype(q->t_rule) != EORULE) {
|
||||
rule_table[n_rules++] = *q->t_rule++;
|
||||
elmcnt++;
|
||||
if (n_rules >= max_rules-2) {
|
||||
rule_table = (p_gram) ralloc(
|
||||
(p_mem) rule_table,
|
||||
(unsigned)(max_rules+=RULEINCR)*sizeof(t_gram));
|
||||
}
|
||||
}
|
||||
elem = *--(q->t_rule);
|
||||
n_rules--;
|
||||
elmcnt--;
|
||||
if (q == t_list - 1) {
|
||||
t_list--;
|
||||
nterms--;
|
||||
t_cnt++;
|
||||
}
|
||||
termdeleted = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
] { if (!termdeleted && g_gettype(&elem) == TERM) {
|
||||
register p_term q;
|
||||
|
||||
q = g_getterm(&elem);
|
||||
r_setkind(q,kind);
|
||||
r_setnum(q,cnt);
|
||||
if ((q->t_flags & RESOLVER) &&
|
||||
(kind == PLUS || kind == FIXED)) {
|
||||
error(linecount,
|
||||
"%%while not allowed in this term");
|
||||
}
|
||||
/*
|
||||
* A persistent fixed term is the same
|
||||
* as a non-persistent fixed term.
|
||||
* Should we complain?
|
||||
if ((q->t_flags & PERSISTENT) &&
|
||||
kind == FIXED) {
|
||||
error(linecount,
|
||||
"Illegal %%persistent");
|
||||
}
|
||||
*/
|
||||
}
|
||||
termdeleted = 0;
|
||||
elmcnt++;
|
||||
rule_table[n_rules++] = elem;
|
||||
}
|
||||
]* { register p_term q;
|
||||
|
||||
g_settype((&rule_table[n_rules]),EORULE);
|
||||
*p = 0;
|
||||
n_rules -= elmcnt;
|
||||
if (g_gettype(&rule_table[n_rules]) == TERM &&
|
||||
elmcnt == 1) {
|
||||
q = g_getterm(&rule_table[n_rules]);
|
||||
if (r_getkind(q) == FIXED &&
|
||||
r_getnum(q) == 0) {
|
||||
*p = q->t_rule;
|
||||
}
|
||||
}
|
||||
if (!*p) *p = copyrule(&rule_table[n_rules],
|
||||
elmcnt+1);
|
||||
}
|
||||
;
|
||||
{
|
||||
|
||||
STATIC
|
||||
mkterm(prod,flags,lc,result) p_gram prod; register p_gram result; {
|
||||
/*
|
||||
* Create a term, initialise it and return
|
||||
* a grammar element containing it
|
||||
*/
|
||||
register p_term q;
|
||||
|
||||
if (! t_cnt) {
|
||||
t_cnt = 50;
|
||||
t_list = (p_term) alloc(50 * sizeof(t_term));
|
||||
}
|
||||
t_cnt--;
|
||||
q = t_list++;
|
||||
q->t_rule = prod;
|
||||
q->t_contains = 0;
|
||||
q->t_flags = flags;
|
||||
g_settype(result,TERM);
|
||||
g_setterm(result,q);
|
||||
result->g_lineno = lc;
|
||||
nterms++;
|
||||
}
|
||||
}
|
||||
|
||||
elem (register p_gram pres;)
|
||||
{ register int t = 0;
|
||||
p_gram p1;
|
||||
int ln;
|
||||
p_gram pe;
|
||||
} :
|
||||
'[' { ln = linecount; }
|
||||
[ C_WHILE expr { t |= RESOLVER; }
|
||||
]?
|
||||
[ C_PERSISTENT { t |= PERSISTENT; }
|
||||
]?
|
||||
productions(&p1)
|
||||
']' {
|
||||
mkterm(p1,t,ln,pres);
|
||||
}
|
||||
|
|
||||
C_IDENT { pe = search(UNKNOWN,lextoken.t_string,BOTH);
|
||||
*pres = *pe;
|
||||
}
|
||||
[ params { if (nparams > 15) {
|
||||
error(linecount,"Too many parameters");
|
||||
} else g_setnpar(pres,nparams);
|
||||
if (g_gettype(pres) == TERMINAL) {
|
||||
error(linecount,
|
||||
"Terminal with parameters");
|
||||
}
|
||||
}
|
||||
]?
|
||||
| C_LITERAL { pe = search(LITERAL,lextoken.t_string,BOTH);
|
||||
*pres = *pe;
|
||||
}
|
||||
| { g_settype(pres,ACTION);
|
||||
pres->g_lineno = linecount;
|
||||
}
|
||||
action(1)
|
||||
;
|
||||
|
||||
params
|
||||
{
|
||||
long off = ftell(fact);
|
||||
}
|
||||
: '(' { copyact('(',')',0,0); }
|
||||
')'
|
||||
{ if (nparams == 0) {
|
||||
fseek(fact, off, 0);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
expr : '(' { copyact('(',')',1,0); }
|
||||
')'
|
||||
;
|
||||
|
||||
repeats(int *kind; int *cnt;) { int t1 = 0; } :
|
||||
[
|
||||
'?' { *kind = OPT; }
|
||||
| [ '*' { *kind = STAR; }
|
||||
| '+' { *kind = PLUS; }
|
||||
]
|
||||
number(&t1)?
|
||||
{ if (t1 == 1) {
|
||||
t1 = 0;
|
||||
if (*kind == STAR) *kind = OPT;
|
||||
if (*kind == PLUS) *kind = FIXED;
|
||||
}
|
||||
}
|
||||
| number(&t1)
|
||||
] { *cnt = t1; }
|
||||
;
|
||||
|
||||
number(int *t;)
|
||||
: C_NUMBER
|
||||
{ *t = lextoken.t_num;
|
||||
if (*t <= 0 || *t >= 8192) {
|
||||
error(linecount,"Illegal number");
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
firsts { register string p; }
|
||||
: C_FIRST C_IDENT
|
||||
{ p = store(lextoken.t_string); }
|
||||
',' C_IDENT ';'
|
||||
{ /*
|
||||
* Store this %first in the list belonging
|
||||
* to this input file
|
||||
*/
|
||||
p_gram temp;
|
||||
register p_first ff;
|
||||
|
||||
temp = search(NONTERM,lextoken.t_string,BOTH);
|
||||
ff = (p_first) alloc(sizeof(t_first));
|
||||
ff->ff_nont = g_getcont(temp);
|
||||
ff->ff_name = p;
|
||||
ff->ff_next = pfile->f_firsts;
|
||||
pfile->f_firsts = ff;
|
||||
}
|
||||
;
|
||||
{
|
||||
|
||||
STATIC
|
||||
copyact(ch1,ch2,flag,level) char ch1,ch2; {
|
||||
/*
|
||||
* Copy an action to file f. Opening bracket is ch1, closing bracket
|
||||
* is ch2.
|
||||
* If flag != 0, copy opening and closing parameters too.
|
||||
*/
|
||||
static int text_seen = 0;
|
||||
register FILE *f;
|
||||
register ch; /* Current char */
|
||||
register match; /* used to read strings */
|
||||
int saved; /* save linecount */
|
||||
|
||||
f = fact;
|
||||
if (!level) {
|
||||
saved = linecount;
|
||||
text_seen = 0;
|
||||
nparams = 0; /* count comma's */
|
||||
putc('\0',f);
|
||||
fprintf(f,"# line %d \"%s\"\n", linecount,f_input);
|
||||
}
|
||||
if (level || flag) putc(ch1,f);
|
||||
for (;;) {
|
||||
ch = input();
|
||||
if (ch == ch2) {
|
||||
if (!level) {
|
||||
unput(ch);
|
||||
if (text_seen) nparams++;
|
||||
}
|
||||
if (level || flag) putc(ch,f);
|
||||
return;
|
||||
}
|
||||
switch(ch) {
|
||||
case ')':
|
||||
case '}':
|
||||
case ']':
|
||||
error(linecount,"Parentheses mismatch");
|
||||
break;
|
||||
case '(':
|
||||
text_seen = 1;
|
||||
copyact('(',')',flag,level+1);
|
||||
continue;
|
||||
case '{':
|
||||
text_seen = 1;
|
||||
copyact('{','}',flag,level+1);
|
||||
continue;
|
||||
case '[':
|
||||
text_seen = 1;
|
||||
copyact('[',']',flag,level+1);
|
||||
continue;
|
||||
case '/':
|
||||
ch = input();
|
||||
unput(ch);
|
||||
if (ch == '*') {
|
||||
putc('/', f);
|
||||
skipcomment(1);
|
||||
continue;
|
||||
}
|
||||
ch = '/';
|
||||
text_seen = 1;
|
||||
break;
|
||||
case ';':
|
||||
case ',':
|
||||
if (! level && text_seen) {
|
||||
text_seen = 0;
|
||||
nparams++;
|
||||
}
|
||||
break;
|
||||
case '\'':
|
||||
case '"' :
|
||||
/*
|
||||
* watch out for brackets in strings, they do not
|
||||
* count !
|
||||
*/
|
||||
text_seen = 1;
|
||||
match = ch;
|
||||
putc(ch,f);
|
||||
while((ch = input())) {
|
||||
if (ch == match) break;
|
||||
if (ch == '\\') {
|
||||
putc(ch,f);
|
||||
ch = input();
|
||||
}
|
||||
if (ch == '\n') {
|
||||
error(linecount,"Newline in string");
|
||||
unput(match);
|
||||
}
|
||||
putc(ch,f);
|
||||
}
|
||||
if (ch == match) break;
|
||||
/* Fall through */
|
||||
case EOF :
|
||||
if (!level) error(saved,"Action does not terminate");
|
||||
return;
|
||||
default:
|
||||
if (c_class[ch] != ISSPA) text_seen = 1;
|
||||
}
|
||||
putc(ch,f);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC p_gram
|
||||
copyrule(p,length) register p_gram p; {
|
||||
/*
|
||||
* Returns a pointer to a grammar rule that was created in
|
||||
* p. The space pointed to by p can now be reused
|
||||
*/
|
||||
register p_gram t;
|
||||
p_gram rule;
|
||||
|
||||
t = (p_gram) alloc((unsigned) length * sizeof(t_gram));
|
||||
rule = t;
|
||||
while (length--) {
|
||||
*t++ = *p++;
|
||||
}
|
||||
return rule;
|
||||
}
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
# $Id$
|
||||
PROF=
|
||||
LLOPT= # -vvv -x
|
||||
INCLUDES =
|
||||
DEFINES = -DNDEBUG
|
||||
CFLAGS=-O $(DEFINES) $(INCLUDES) $(PROF)
|
||||
LDFLAGS=
|
||||
OBJECTS = main.o gencode.o compute.o LLgen.o tokens.o check.o reach.o global.o name.o sets.o Lpars.o alloc.o machdep.o cclass.o
|
||||
CFILES = main.c gencode.c compute.c LLgen.c tokens.c check.c reach.c global.c name.c sets.c Lpars.c alloc.c machdep.c cclass.c
|
||||
FILES =types.h extern.h io.h sets.h tokens.g LLgen.g main.c name.c compute.c sets.c gencode.c global.c check.c reach.c alloc.c machdep.c Makefile cclass.c
|
||||
GFILES = tokens.g LLgen.g
|
||||
LINT = lint -b $(DEFINES) -DNORCSID
|
||||
|
||||
LIBDIRSTR = \"$(LIBDIR)\"
|
||||
|
||||
all: parser
|
||||
@make LLgen "LDFLAGS=$(LDFLAGS)" "CC=$(CC)" "CFLAGS=$(CFLAGS)" "PROF=$(PROF)" "LIBDIR=$(LIBDIR)"
|
||||
|
||||
parser: $(GFILES)
|
||||
LLgen $(LLOPT) $(GFILES)
|
||||
@touch parser
|
||||
|
||||
first: firstparser
|
||||
@make LLgen "LDFLAGS=$(LDFLAGS)" "CC=$(CC)" "CFLAGS=$(CFLAGS)" "PROF=$(PROF)" "LIBDIR=$(LIBDIR)"
|
||||
|
||||
firstparser:
|
||||
cp LLgen.c.dist LLgen.c
|
||||
cp tokens.c.dist tokens.c
|
||||
cp Lpars.c.dist Lpars.c
|
||||
cp Lpars.h.dist Lpars.h
|
||||
@touch parser
|
||||
|
||||
LLgen: $(OBJECTS)
|
||||
$(CC) $(PROF) $(LDFLAGS) $(OBJECTS) -o LLgen
|
||||
@size LLgen
|
||||
|
||||
pr :
|
||||
@pr $(FILES) ../lib/rec ../lib/incl Makefile
|
||||
|
||||
lint:
|
||||
$(LINT) $(INCLUDES) -DLIBDIR=$(LIBDIRSTR) $(CFILES)
|
||||
|
||||
clean:
|
||||
-rm -f *.o LL.temp LL.xxx LL.output LLgen LLgen.c tokens.c Lpars.[ch] parser
|
||||
|
||||
distr:
|
||||
-rm -f parser
|
||||
make parser
|
||||
cp Lpars.c Lpars.c.dist
|
||||
cp Lpars.h Lpars.h.dist
|
||||
cp LLgen.c LLgen.c.dist
|
||||
cp tokens.c tokens.c.dist
|
||||
|
||||
machdep.o: machdep.c
|
||||
$(CC) -c $(CFLAGS) -DLIBDIR=$(LIBDIRSTR) machdep.c
|
||||
|
||||
# The next lines are generated automatically
|
||||
# AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
|
||||
LLgen.o: Lpars.h
|
||||
LLgen.o: cclass.h
|
||||
LLgen.o: extern.h
|
||||
LLgen.o: io.h
|
||||
LLgen.o: types.h
|
||||
Lpars.o: Lpars.h
|
||||
alloc.o: extern.h
|
||||
alloc.o: types.h
|
||||
cclass.o: cclass.h
|
||||
check.o: extern.h
|
||||
check.o: io.h
|
||||
check.o: sets.h
|
||||
check.o: types.h
|
||||
compute.o: extern.h
|
||||
compute.o: io.h
|
||||
compute.o: sets.h
|
||||
compute.o: types.h
|
||||
gencode.o: cclass.h
|
||||
gencode.o: extern.h
|
||||
gencode.o: io.h
|
||||
gencode.o: sets.h
|
||||
gencode.o: types.h
|
||||
global.o: extern.h
|
||||
global.o: io.h
|
||||
global.o: types.h
|
||||
machdep.o: types.h
|
||||
main.o: extern.h
|
||||
main.o: io.h
|
||||
main.o: sets.h
|
||||
main.o: types.h
|
||||
name.o: extern.h
|
||||
name.o: io.h
|
||||
name.o: types.h
|
||||
reach.o: extern.h
|
||||
reach.o: io.h
|
||||
reach.o: types.h
|
||||
sets.o: extern.h
|
||||
sets.o: sets.h
|
||||
sets.o: types.h
|
||||
tokens.o: Lpars.h
|
||||
tokens.o: cclass.h
|
||||
tokens.o: extern.h
|
||||
tokens.o: io.h
|
||||
tokens.o: types.h
|
||||
@@ -1,91 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* alloc.c
|
||||
* Interface to malloc() and realloc()
|
||||
*/
|
||||
|
||||
# include "types.h"
|
||||
# include "extern.h"
|
||||
|
||||
# ifndef NORCSID
|
||||
static string rcsid = "$Id$";
|
||||
# endif
|
||||
|
||||
static string e_nomem = "Out of memory";
|
||||
|
||||
p_mem
|
||||
alloc(size) unsigned size; {
|
||||
/*
|
||||
Allocate "size" bytes. Panic if it fails
|
||||
*/
|
||||
p_mem p;
|
||||
p_mem malloc();
|
||||
|
||||
if ((p = malloc(size)) == 0) fatal(linecount,e_nomem);
|
||||
return p;
|
||||
}
|
||||
|
||||
p_mem
|
||||
ralloc(p,size) p_mem p; unsigned size; {
|
||||
/*
|
||||
Re-allocate the chunk of memory indicated by "p", to
|
||||
occupy "size" bytes
|
||||
*/
|
||||
p_mem realloc();
|
||||
|
||||
if ((p = realloc(p,size)) == 0) fatal(linecount,e_nomem);
|
||||
return p;
|
||||
}
|
||||
|
||||
p_mem
|
||||
new_mem(p) register p_info p; {
|
||||
/*
|
||||
This routine implements arrays that can grow.
|
||||
It must be called every time a new element is added to it.
|
||||
Also, the array has associated with it a "info_alloc" structure,
|
||||
which contains info on the element size, total allocated size,
|
||||
a pointer to the array, a pointer to the first free element,
|
||||
and a pointer to the top.
|
||||
If the base of the array is remembered elsewhere, it should
|
||||
be updated each time this routine is called
|
||||
*/
|
||||
p_mem rp;
|
||||
unsigned sz;
|
||||
|
||||
if (p->i_max >= p->i_top) { /* No more free elements */
|
||||
sz = p->i_size;
|
||||
if (sizeof(char *) > 2) {
|
||||
/*
|
||||
Do not worry about size. Just double it.
|
||||
*/
|
||||
p->i_size += p->i_size;
|
||||
if (! p->i_size)
|
||||
p->i_size += p->i_incr * p->i_esize;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
Worry about size, so only increment in chunks of i_incr.
|
||||
*/
|
||||
p->i_size += p->i_incr * p->i_esize;
|
||||
}
|
||||
p->i_ptr = !p->i_ptr ?
|
||||
alloc(p->i_size) :
|
||||
ralloc(p->i_ptr, p->i_size);
|
||||
p->i_max = p->i_ptr + sz;
|
||||
p->i_top = p->i_ptr + p->i_size;
|
||||
}
|
||||
rp = p->i_max;
|
||||
p->i_max += p->i_esize;
|
||||
return rp;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* assert.h $Header$
|
||||
* an assertion macro
|
||||
*/
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define assert(x) if(!(x)) badassertion("x",__FILE__,__LINE__)
|
||||
#else
|
||||
#define assert(x) /* nothing */
|
||||
#endif
|
||||
@@ -1,137 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#include "cclass.h"
|
||||
char c_class[] = {
|
||||
0, /* 00 */
|
||||
0, /* 01 */
|
||||
0, /* 02 */
|
||||
0, /* 03 */
|
||||
0, /* 04 */
|
||||
0, /* 05 */
|
||||
0, /* 06 */
|
||||
0, /* 07 */
|
||||
0, /* 010 */
|
||||
ISSPA, /* 011 */
|
||||
ISSPA, /* 012 */
|
||||
0, /* 013 */
|
||||
ISSPA, /* 014 */
|
||||
ISSPA, /* 015 */
|
||||
0, /* 016 */
|
||||
0, /* 017 */
|
||||
0, /* 020 */
|
||||
0, /* 021 */
|
||||
0, /* 022 */
|
||||
0, /* 023 */
|
||||
0, /* 024 */
|
||||
0, /* 025 */
|
||||
0, /* 026 */
|
||||
0, /* 027 */
|
||||
0, /* 030 */
|
||||
0, /* 031 */
|
||||
0, /* 032 */
|
||||
0, /* 033 */
|
||||
0, /* 034 */
|
||||
0, /* 035 */
|
||||
0, /* 036 */
|
||||
0, /* 037 */
|
||||
ISSPA, /* ' ' */
|
||||
0, /* '!' */
|
||||
0, /* '"' */
|
||||
0, /* '#' */
|
||||
0, /* '$' */
|
||||
ISKEY, /* '%' */
|
||||
0, /* '&' */
|
||||
ISLIT, /* ''' */
|
||||
ISTOK, /* '(' */
|
||||
ISTOK, /* ')' */
|
||||
ISTOK, /* '*' */
|
||||
ISTOK, /* '+' */
|
||||
ISTOK, /* ',' */
|
||||
0, /* '-' */
|
||||
0, /* '.' */
|
||||
ISCOM, /* '/' */
|
||||
ISDIG, /* '0' */
|
||||
ISDIG, /* '1' */
|
||||
ISDIG, /* '2' */
|
||||
ISDIG, /* '3' */
|
||||
ISDIG, /* '4' */
|
||||
ISDIG, /* '5' */
|
||||
ISDIG, /* '6' */
|
||||
ISDIG, /* '7' */
|
||||
ISDIG, /* '8' */
|
||||
ISDIG, /* '9' */
|
||||
ISTOK, /* ':' */
|
||||
ISTOK, /* ';' */
|
||||
0, /* '<' */
|
||||
0, /* '=' */
|
||||
0, /* '>' */
|
||||
ISTOK, /* '?' */
|
||||
0, /* '@' */
|
||||
ISLET, /* 'A' */
|
||||
ISLET, /* 'B' */
|
||||
ISLET, /* 'C' */
|
||||
ISLET, /* 'D' */
|
||||
ISLET, /* 'E' */
|
||||
ISLET, /* 'F' */
|
||||
ISLET, /* 'G' */
|
||||
ISLET, /* 'H' */
|
||||
ISLET, /* 'I' */
|
||||
ISLET, /* 'J' */
|
||||
ISLET, /* 'K' */
|
||||
ISLET, /* 'L' */
|
||||
ISLET, /* 'M' */
|
||||
ISLET, /* 'N' */
|
||||
ISLET, /* 'O' */
|
||||
ISLET, /* 'P' */
|
||||
ISLET, /* 'Q' */
|
||||
ISLET, /* 'R' */
|
||||
ISLET, /* 'S' */
|
||||
ISLET, /* 'T' */
|
||||
ISLET, /* 'U' */
|
||||
ISLET, /* 'V' */
|
||||
ISLET, /* 'W' */
|
||||
ISLET, /* 'X' */
|
||||
ISLET, /* 'Y' */
|
||||
ISLET, /* 'Z' */
|
||||
ISTOK, /* '[' */
|
||||
0, /* '\' */
|
||||
ISTOK, /* ']' */
|
||||
0, /* '^' */
|
||||
ISLET, /* '_' */
|
||||
0, /* '`' */
|
||||
ISLET, /* 'a' */
|
||||
ISLET, /* 'b' */
|
||||
ISLET, /* 'c' */
|
||||
ISLET, /* 'd' */
|
||||
ISLET, /* 'e' */
|
||||
ISLET, /* 'f' */
|
||||
ISLET, /* 'g' */
|
||||
ISLET, /* 'h' */
|
||||
ISLET, /* 'i' */
|
||||
ISLET, /* 'j' */
|
||||
ISLET, /* 'k' */
|
||||
ISLET, /* 'l' */
|
||||
ISLET, /* 'm' */
|
||||
ISLET, /* 'n' */
|
||||
ISLET, /* 'o' */
|
||||
ISLET, /* 'p' */
|
||||
ISLET, /* 'q' */
|
||||
ISLET, /* 'r' */
|
||||
ISLET, /* 's' */
|
||||
ISLET, /* 't' */
|
||||
ISLET, /* 'u' */
|
||||
ISLET, /* 'v' */
|
||||
ISLET, /* 'w' */
|
||||
ISLET, /* 'x' */
|
||||
ISLET, /* 'y' */
|
||||
ISLET, /* 'z' */
|
||||
ISTOK, /* '{' */
|
||||
ISTOK, /* '|' */
|
||||
ISTOK, /* '}' */
|
||||
0, /* '~' */
|
||||
0 /* 0177 */
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
extern char c_class[];
|
||||
|
||||
#define ISLET 1
|
||||
#define ISDIG 2
|
||||
#define ISSPA 3
|
||||
#define ISKEY 4
|
||||
#define ISTOK 5
|
||||
#define ISCOM 6
|
||||
#define ISLIT 7
|
||||
@@ -1,472 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* check.c
|
||||
* Several routines to perform checks and printouts
|
||||
*/
|
||||
|
||||
# include "types.h"
|
||||
# include "extern.h"
|
||||
# include "io.h"
|
||||
# include "sets.h"
|
||||
# include "assert.h"
|
||||
|
||||
# ifndef NORCSID
|
||||
static string rcsid1 = "$Id$";
|
||||
# endif
|
||||
|
||||
|
||||
static string c_first = "> firstset ";
|
||||
static string c_contains = "> containset ";
|
||||
static string c_follow = "> followset ";
|
||||
p_set setalloc();
|
||||
static int level;
|
||||
|
||||
/* In this file are defined : */
|
||||
extern conflchecks();
|
||||
STATIC prline();
|
||||
STATIC printset();
|
||||
STATIC int check();
|
||||
STATIC moreverbose();
|
||||
STATIC prrule();
|
||||
STATIC cfcheck();
|
||||
STATIC resolve();
|
||||
STATIC propagate();
|
||||
STATIC spaces();
|
||||
|
||||
conflchecks() {
|
||||
/*
|
||||
* Check for conflicts, that is,
|
||||
* in a repeating term, the FIRST and FOLLOW must be disjunct,
|
||||
* unless there is a disambiguating condition.
|
||||
* in an alternation, the sets that determine the direction to take,
|
||||
* must be disjunct.
|
||||
*/
|
||||
register p_nont p;
|
||||
register int s;
|
||||
p_file x = files;
|
||||
|
||||
f_input = x->f_name;
|
||||
if (verbose >= 3) {
|
||||
for (p = nonterms; p < maxnt; p++) p->n_flags |= VERBOSE;
|
||||
}
|
||||
if (verbose) {
|
||||
if ((fout = fopen(f_out,"w")) == NULL) fatal(1,e_noopen,f_out);
|
||||
}
|
||||
/*
|
||||
* Check the rules in the order in which they are declared,
|
||||
* and input file by input file, to give proper error messages
|
||||
*/
|
||||
for (; x < maxfiles; x++) {
|
||||
f_input = x->f_name;
|
||||
for (s = x->f_nonterminals; s != -1; s = p->n_next) {
|
||||
p = &nonterms[s];
|
||||
if (check(p->n_rule)) p->n_flags |= VERBOSE;
|
||||
}
|
||||
}
|
||||
for (x = files; x < maxfiles; x++) {
|
||||
f_input = x->f_name;
|
||||
for (s = x->f_nonterminals; s != -1; s = p->n_next) {
|
||||
p = &nonterms[s];
|
||||
if (p->n_flags & RECURSIVE) {
|
||||
error(p->n_lineno,
|
||||
"Recursion in default for nonterminal %s",
|
||||
p->n_name);
|
||||
}
|
||||
/*
|
||||
* If a printout is needed for this rule in
|
||||
* LL.output, just do it
|
||||
*/
|
||||
if (verbose && (p->n_flags & VERBOSE)) {
|
||||
fprintf(fout,"\n%s :\n",p->n_name);
|
||||
printset(p->n_first,c_first);
|
||||
printset(p->n_contains,c_contains);
|
||||
printset(p->n_follow,c_follow);
|
||||
fprintf(fout,"> rule%s\n\t",
|
||||
p->n_flags&EMPTY ? "\t(EMPTY producing)" : "");
|
||||
level = 8;
|
||||
prrule(p->n_rule);
|
||||
level = 0;
|
||||
prline("\n");
|
||||
}
|
||||
/*
|
||||
* Now, the conflicts may be resolved
|
||||
*/
|
||||
resolve(p->n_rule);
|
||||
}
|
||||
}
|
||||
if (verbose) fclose(fout);
|
||||
}
|
||||
|
||||
STATIC
|
||||
prline(s) char *s; {
|
||||
fputs(s, fout);
|
||||
spaces();
|
||||
}
|
||||
|
||||
STATIC
|
||||
printset(p,s) register p_set p; string s; {
|
||||
/*
|
||||
* Print the elements of a set
|
||||
*/
|
||||
register int i;
|
||||
register int j;
|
||||
register p_token pt;
|
||||
string name;
|
||||
int k;
|
||||
int hulp;
|
||||
|
||||
k = strlen(s) + 2 + level;
|
||||
/*
|
||||
* k contains relative level of indentation
|
||||
*/
|
||||
fprintf(fout,"%s{ ",s);
|
||||
j = k;
|
||||
/*
|
||||
* j will gather the total length of the line
|
||||
*/
|
||||
for (i = 0, pt = tokens; i < ntokens; i++,pt++) {
|
||||
if (IN(p,i)) {
|
||||
hulp = strlen(pt->t_string)+1;
|
||||
if (pt->t_tokno < 0400) hulp += 2;
|
||||
if ((j += hulp) >= 78) {
|
||||
/*
|
||||
* Line becoming too long
|
||||
*/
|
||||
j = k+hulp;
|
||||
prline("\n");
|
||||
fprintf(fout,">%*c",k - level - 1,' ');
|
||||
}
|
||||
fprintf(fout, pt->t_tokno<0400 ? "'%s' " : "%s ",pt->t_string);
|
||||
}
|
||||
}
|
||||
if (ntprint) for (i = 0; i < nnonterms; i++) {
|
||||
/*
|
||||
* Nonterminals in the set must also be printed
|
||||
*/
|
||||
if (NTIN(p,i)) {
|
||||
name = nonterms[i].n_name;
|
||||
hulp = strlen(name) + 3;
|
||||
if ((j += hulp) >= 78) {
|
||||
j = k + hulp;
|
||||
prline("\n");
|
||||
fprintf(fout,">%*c",k - level - 1,' ');
|
||||
}
|
||||
fprintf(fout,"<%s> ",name);
|
||||
}
|
||||
}
|
||||
prline("}\n");
|
||||
}
|
||||
|
||||
STATIC int
|
||||
check(p) register p_gram p; {
|
||||
/*
|
||||
* Search for conflicts in a grammar rule.
|
||||
*/
|
||||
register p_set temp;
|
||||
register int retval;
|
||||
|
||||
retval = 0;
|
||||
for (;;) {
|
||||
switch (g_gettype(p)) {
|
||||
case EORULE :
|
||||
return retval;
|
||||
case NONTERM : {
|
||||
register p_nont n;
|
||||
|
||||
n = &nonterms[g_getcont(p)];
|
||||
if (g_getnpar(p) != getntparams(n)) {
|
||||
error(p->g_lineno,
|
||||
"Call of %s: parameter count mismatch",
|
||||
n->n_name);
|
||||
}
|
||||
break; }
|
||||
case TERM : {
|
||||
register p_term q;
|
||||
|
||||
q = g_getterm(p);
|
||||
retval |= check(q->t_rule);
|
||||
if (r_getkind(q) == FIXED) break;
|
||||
if (setempty(q->t_first)) {
|
||||
q->t_flags |= EMPTYFIRST;
|
||||
retval = 1;
|
||||
error(p->g_lineno, "No symbols in term");
|
||||
}
|
||||
if (empty(q->t_rule)) {
|
||||
q->t_flags |= EMPTYTERM;
|
||||
retval = 1;
|
||||
error(p->g_lineno, "Term with variable repetition count produces empty");
|
||||
}
|
||||
temp = setalloc();
|
||||
setunion(temp,q->t_first);
|
||||
if (!setintersect(temp,q->t_follow)) {
|
||||
/*
|
||||
* q->t_first * q->t_follow != EMPTY
|
||||
*/
|
||||
if (!(q->t_flags & RESOLVER)) {
|
||||
/*
|
||||
* No conflict resolver
|
||||
*/
|
||||
error(p->g_lineno,
|
||||
"Repetition conflict");
|
||||
retval = 1;
|
||||
moreverbose(temp);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (q->t_flags & RESOLVER) {
|
||||
q->t_flags |= NOCONF;
|
||||
warning(p->g_lineno,
|
||||
"%%while without conflict");
|
||||
}
|
||||
}
|
||||
free((p_mem) temp);
|
||||
break; }
|
||||
case ALTERNATION : {
|
||||
register p_link l;
|
||||
|
||||
l = g_getlink(p);
|
||||
temp = setalloc();
|
||||
setunion(temp,l->l_symbs);
|
||||
if(!setintersect(temp,l->l_others)) {
|
||||
/*
|
||||
* temp now contains the conflicting
|
||||
* symbols
|
||||
*/
|
||||
if (!(l->l_flag & (COND|PREFERING|AVOIDING))) {
|
||||
error(p->g_lineno,
|
||||
"Alternation conflict");
|
||||
retval = 1;
|
||||
moreverbose(temp);
|
||||
}
|
||||
} else {
|
||||
if (l->l_flag & (COND|PREFERING|AVOIDING)) {
|
||||
l->l_flag |= NOCONF;
|
||||
warning(p->g_lineno,
|
||||
"Conflict resolver without conflict");
|
||||
}
|
||||
}
|
||||
if (l->l_flag & PREFERING) propagate(l->l_symbs,p+1);
|
||||
free( (p_mem) temp);
|
||||
retval |= check(l->l_rule);
|
||||
break; }
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
moreverbose(t) register p_set t; {
|
||||
/*
|
||||
* t points to a set containing conflicting symbols and pssibly
|
||||
* also containing nonterminals.
|
||||
* Take care that a printout will be prepared for these nonterminals
|
||||
*/
|
||||
register int i;
|
||||
register p_nont p;
|
||||
|
||||
if (verbose == 2) for (i = 0, p = nonterms; i < nnonterms; i++, p++) {
|
||||
if (NTIN(t,i)) p->n_flags |= VERBOSE;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
prrule(p) register p_gram p; {
|
||||
/*
|
||||
* Create a verbose printout of grammar rule p
|
||||
*/
|
||||
register FILE *f;
|
||||
int present = 0;
|
||||
int firstalt = 1;
|
||||
|
||||
f = fout;
|
||||
for (;;) {
|
||||
switch (g_gettype(p)) {
|
||||
case EORULE :
|
||||
fputs("\n",f);
|
||||
return;
|
||||
case TERM : {
|
||||
register p_term q;
|
||||
register int c;
|
||||
|
||||
q = g_getterm(p);
|
||||
if (present) prline("\n");
|
||||
fputs("[ ",f);
|
||||
level += 4;
|
||||
if (q->t_flags & RESOLVER) {
|
||||
prline("%while (..)\n");
|
||||
}
|
||||
if (q->t_flags & PERSISTENT) {
|
||||
prline("%persistent\n");
|
||||
}
|
||||
if (r_getkind(q) != FIXED) {
|
||||
if (!(q->t_flags & PERSISTENT)) {
|
||||
prline("> continue repetition on the\n");
|
||||
}
|
||||
printset(q->t_first, c_first);
|
||||
if (q->t_flags & PERSISTENT) {
|
||||
prline("> continue repetition on the\n");
|
||||
}
|
||||
printset(q->t_contains, c_contains);
|
||||
prline("> terminate repetition on the\n");
|
||||
printset(q->t_follow,c_follow);
|
||||
if (q->t_flags & EMPTYFIRST) {
|
||||
prline(">>> empty first\n");
|
||||
}
|
||||
if (q->t_flags & EMPTYTERM) {
|
||||
prline(">>> term produces empty\n");
|
||||
}
|
||||
cfcheck(q->t_first,q->t_follow,
|
||||
q->t_flags & RESOLVER);
|
||||
}
|
||||
prrule(q->t_rule);
|
||||
level -= 4;
|
||||
spaces();
|
||||
c = r_getkind(q);
|
||||
fputs(c == STAR ? "]*" : c == PLUS ? "]+" :
|
||||
c == OPT ? "]?" : "]", f);
|
||||
if (c = r_getnum(q)) {
|
||||
fprintf(f,"%d",c);
|
||||
}
|
||||
prline("\n");
|
||||
break; }
|
||||
case ACTION :
|
||||
fputs("{..} ",f);
|
||||
break;
|
||||
case ALTERNATION : {
|
||||
register p_link l;
|
||||
|
||||
l = g_getlink(p);
|
||||
if (firstalt) {
|
||||
firstalt = 0;
|
||||
}
|
||||
else prline("|\n");
|
||||
printset(l->l_symbs,"> alternative on ");
|
||||
cfcheck(l->l_symbs,
|
||||
l->l_others,
|
||||
(int)(l->l_flag&(COND|PREFERING|AVOIDING)));
|
||||
fputs(" ",f);
|
||||
level += 4;
|
||||
if (l->l_flag & DEF) {
|
||||
prline("%default\n");
|
||||
}
|
||||
if (l->l_flag & AVOIDING) {
|
||||
prline("%avoid\n");
|
||||
}
|
||||
if (l->l_flag & PREFERING) {
|
||||
prline("%prefer\n");
|
||||
}
|
||||
if (l->l_flag & COND) {
|
||||
prline("%if ( ... )\n");
|
||||
}
|
||||
prrule(l->l_rule);
|
||||
level -= 4;
|
||||
if (g_gettype(p+1) == EORULE) {
|
||||
return;
|
||||
}
|
||||
spaces();
|
||||
p++; continue; }
|
||||
case LITERAL :
|
||||
case TERMINAL : {
|
||||
register p_token pt = &tokens[g_getcont(p)];
|
||||
|
||||
fprintf(f,pt->t_tokno<0400 ?
|
||||
"'%s' " : "%s ", pt->t_string);
|
||||
break; }
|
||||
case NONTERM :
|
||||
fprintf(f,"%s ",nonterms[g_getcont(p)].n_name);
|
||||
break;
|
||||
}
|
||||
p++;
|
||||
present = 1;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
cfcheck(s1,s2,flag) p_set s1,s2; {
|
||||
/*
|
||||
* Check if s1 and s2 have elements in common.
|
||||
* If so, flag must be non-zero, indicating that there is a
|
||||
* conflict resolver, otherwise, flag must be zero, indicating
|
||||
* that there is not.
|
||||
*/
|
||||
register p_set temp;
|
||||
|
||||
temp = setalloc();
|
||||
setunion(temp,s1);
|
||||
if (!setintersect(temp,s2)) {
|
||||
if (! flag) {
|
||||
printset(temp,">>> conflict on ");
|
||||
prline("\n");
|
||||
}
|
||||
} else {
|
||||
if (flag) {
|
||||
prline(">>> %if/%while, no conflict\n");
|
||||
}
|
||||
}
|
||||
free((p_mem) temp);
|
||||
}
|
||||
|
||||
STATIC
|
||||
resolve(p) register p_gram p; {
|
||||
/*
|
||||
* resolve conflicts, as specified by the user
|
||||
*/
|
||||
for (;;) {
|
||||
switch (g_gettype(p)) {
|
||||
case EORULE :
|
||||
return;
|
||||
case TERM :
|
||||
resolve(g_getterm(p)->t_rule);
|
||||
break;
|
||||
case ALTERNATION : {
|
||||
register p_link l;
|
||||
|
||||
l = g_getlink(p);
|
||||
if (l->l_flag & AVOIDING) {
|
||||
/*
|
||||
* On conflicting symbols, this rule
|
||||
* is never chosen
|
||||
*/
|
||||
setminus(l->l_symbs,l->l_others);
|
||||
}
|
||||
if (setempty(l->l_symbs)) {
|
||||
/*
|
||||
* This may be caused by the statement above
|
||||
*/
|
||||
error(p->g_lineno,"Alternative never chosen");
|
||||
}
|
||||
resolve(l->l_rule);
|
||||
break; }
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
propagate(set,p) p_set set; register p_gram p; {
|
||||
/*
|
||||
* Propagate the fact that on the elements of set the grammar rule
|
||||
* p will not be chosen.
|
||||
*/
|
||||
while (g_gettype(p) != EORULE) {
|
||||
setminus(g_getlink(p)->l_symbs,set);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
spaces() {
|
||||
|
||||
if (level > 0) fprintf(fout,"%*c",level,' ');
|
||||
}
|
||||
@@ -1,921 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* compute.c
|
||||
* Defines routines to compute FIRST, FOLLOW etc.
|
||||
* Also checks the continuation grammar from the specified grammar.
|
||||
*/
|
||||
|
||||
# include "types.h"
|
||||
# include "extern.h"
|
||||
# include "sets.h"
|
||||
# include "assert.h"
|
||||
# include "io.h"
|
||||
|
||||
# ifndef NORCSID
|
||||
static string rcsid = "$Id$";
|
||||
# endif
|
||||
|
||||
p_set get_set();
|
||||
typedef struct lngth {
|
||||
/* Structure used to compute the shortest possible
|
||||
* length of a terminal production of a rule.
|
||||
* In case of a tie, the second field is used.
|
||||
*/
|
||||
int cnt;
|
||||
int val;
|
||||
} t_length, *p_length;
|
||||
|
||||
/* Defined in this file : */
|
||||
extern do_compute();
|
||||
STATIC createsets();
|
||||
STATIC walk();
|
||||
STATIC co_trans();
|
||||
STATIC int nempty();
|
||||
extern empty();
|
||||
STATIC int nfirst();
|
||||
STATIC first();
|
||||
STATIC int nfollow();
|
||||
STATIC follow();
|
||||
STATIC co_dirsymb();
|
||||
STATIC co_others();
|
||||
STATIC do_lengthcomp();
|
||||
STATIC complength();
|
||||
STATIC add();
|
||||
STATIC int compare();
|
||||
STATIC setdefaults();
|
||||
STATIC do_contains();
|
||||
STATIC contains();
|
||||
STATIC int nsafes();
|
||||
STATIC int do_safes();
|
||||
|
||||
do_compute() {
|
||||
/*
|
||||
* Does all the work, by calling other routines (divide and conquer)
|
||||
*/
|
||||
register p_nont p;
|
||||
register p_start st;
|
||||
|
||||
createsets();
|
||||
co_trans(nempty); /* Which nonterminals produce empty? */
|
||||
co_trans(nfirst); /* Computes first sets */
|
||||
/*
|
||||
* Compute FOLLOW sets.
|
||||
* First put EOFILE in the follow set of the start nonterminals.
|
||||
*/
|
||||
for (st = start; st; st = st->ff_next) {
|
||||
p = &nonterms[st->ff_nont];
|
||||
PUTIN(p->n_follow,0);
|
||||
}
|
||||
co_trans(nfollow);
|
||||
/*
|
||||
* Compute the sets which determine which alternative to choose
|
||||
* in case of a choice
|
||||
*/
|
||||
for (p = nonterms; p < maxnt; p++) {
|
||||
co_dirsymb(p->n_follow,p->n_rule);
|
||||
}
|
||||
/*
|
||||
* Compute the minimum length of productions of nonterminals,
|
||||
* and then determine the default choices
|
||||
*/
|
||||
do_lengthcomp();
|
||||
/*
|
||||
* Compute the contains sets
|
||||
*/
|
||||
for (p = nonterms; p < maxnt; p++) do_contains(p);
|
||||
for (p = nonterms; p < maxnt; p++) contains(p->n_rule, (p_set) 0);
|
||||
/*
|
||||
* Compute the safety of each nonterminal and term.
|
||||
* The safety gives an answer to the question whether a scan is done,
|
||||
* and how it should be handled.
|
||||
*/
|
||||
for (p = nonterms; p < maxnt; p++) {
|
||||
/*
|
||||
* Don't know anything yet
|
||||
*/
|
||||
setntsafe(p, NOSAFETY);
|
||||
setntout(p, NOSAFETY);
|
||||
}
|
||||
for (st = start; st; st = st->ff_next) {
|
||||
/*
|
||||
* But start symbols are called with lookahead done
|
||||
*/
|
||||
p = &nonterms[st->ff_nont];
|
||||
setntsafe(p,SCANDONE);
|
||||
}
|
||||
co_trans(nsafes);
|
||||
# ifndef NDEBUG
|
||||
if (debug) {
|
||||
fputs("Safeties:\n", stderr);
|
||||
for (p = nonterms; p < maxnt; p++) {
|
||||
fprintf(stderr, "%s\t%d\t%d\n",
|
||||
p->n_name,
|
||||
getntsafe(p),
|
||||
getntout(p));
|
||||
}
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
STATIC
|
||||
createsets() {
|
||||
/*
|
||||
* Allocate space for the sets. Also determine which files use
|
||||
* which nonterminals, and determine which nonterminals can be
|
||||
* made static.
|
||||
*/
|
||||
register p_nont p;
|
||||
register p_file f;
|
||||
register p_start st;
|
||||
register int i;
|
||||
int n = NINTS(NBYTES(nnonterms));
|
||||
p_mem alloc();
|
||||
|
||||
for (f = files; f < maxfiles; f++) {
|
||||
register p_set s;
|
||||
f->f_used = s = (p_set) alloc((unsigned)n*sizeof(*(f->f_used)));
|
||||
for (i = n; i; i--) *s++ = 0;
|
||||
for (i = f->f_nonterminals; i != -1; i = p->n_next) {
|
||||
p = &nonterms[i];
|
||||
p->n_flags |= GENSTATIC;
|
||||
p->n_first = get_set();
|
||||
p->n_follow = get_set();
|
||||
walk(f->f_used, p->n_rule);
|
||||
}
|
||||
}
|
||||
for (f = files; f < maxfiles; f++) {
|
||||
for (i = f->f_nonterminals; i != -1; i = p->n_next) {
|
||||
register p_file f2;
|
||||
|
||||
p = &nonterms[i];
|
||||
for (f2 = files; f2 < maxfiles; f2++) {
|
||||
if (f2 != f && IN(f2->f_used, i)) {
|
||||
p->n_flags &= ~GENSTATIC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (st = start; st; st = st->ff_next) {
|
||||
nonterms[st->ff_nont].n_flags &= ~GENSTATIC;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
walk(u, p) p_set u; register p_gram p; {
|
||||
/*
|
||||
* Walk through the grammar rule p, allocating sets
|
||||
*/
|
||||
|
||||
for (;;) {
|
||||
switch (g_gettype(p)) {
|
||||
case TERM : {
|
||||
register p_term q;
|
||||
|
||||
q = g_getterm(p);
|
||||
q->t_first = get_set();
|
||||
q->t_follow = get_set();
|
||||
walk(u, q->t_rule);
|
||||
break; }
|
||||
case ALTERNATION : {
|
||||
register p_link l;
|
||||
|
||||
l = g_getlink(p);
|
||||
l->l_symbs = get_set();
|
||||
l->l_others = get_set();
|
||||
walk(u, l->l_rule);
|
||||
break; }
|
||||
case NONTERM : {
|
||||
register int i = g_getcont(p);
|
||||
|
||||
PUTIN(u, i);
|
||||
break; }
|
||||
case EORULE :
|
||||
return;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
co_trans(fc) int (*fc)(); {
|
||||
register p_nont p;
|
||||
register int change;
|
||||
|
||||
do {
|
||||
change = 0;
|
||||
for (p = nonterms; p < maxnt; p++) {
|
||||
if ((*fc)(p)) change = 1;
|
||||
}
|
||||
} while (change);
|
||||
}
|
||||
|
||||
STATIC int
|
||||
nempty(p) register p_nont p; {
|
||||
if (!(p->n_flags & EMPTY) && empty(p->n_rule)) {
|
||||
p->n_flags |= EMPTY;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
empty(p) register p_gram p; {
|
||||
/*
|
||||
* Does the rule pointed to by p produce empty ?
|
||||
*/
|
||||
|
||||
for (;;) {
|
||||
switch (g_gettype(p)) {
|
||||
case EORULE :
|
||||
return 1;
|
||||
case TERM : {
|
||||
register p_term q;
|
||||
|
||||
q = g_getterm(p);
|
||||
if (r_getkind(q) == STAR
|
||||
|| r_getkind(q) == OPT
|
||||
|| empty(q->t_rule) ) break;
|
||||
return 0; }
|
||||
case ALTERNATION :
|
||||
if (empty(g_getlink(p)->l_rule)) {
|
||||
return 1;
|
||||
}
|
||||
if (g_gettype(p+1) == EORULE) return 0;
|
||||
break;
|
||||
case NONTERM :
|
||||
if (nonterms[g_getcont(p)].n_flags & EMPTY) {
|
||||
break;
|
||||
}
|
||||
/* Fall through */
|
||||
case LITERAL :
|
||||
case TERMINAL :
|
||||
return 0;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC int
|
||||
nfirst(p) register p_nont p; {
|
||||
return first(p->n_first, p->n_rule, 0);
|
||||
}
|
||||
|
||||
STATIC
|
||||
first(setp,p,flag) p_set setp; register p_gram p; {
|
||||
/*
|
||||
* Compute the FIRST set of rule p.
|
||||
* If flag = 0, also the first sets for terms and alternations in
|
||||
* the rule p are computed.
|
||||
* The FIRST set is put in setp.
|
||||
* return 1 if the set refered to by "setp" changed
|
||||
*/
|
||||
register s; /* Will gather return value */
|
||||
int noenter;/* when set, unables entering of elements into
|
||||
* setp. This is necessary to walk through the
|
||||
* rest of rule p.
|
||||
*/
|
||||
|
||||
s = 0;
|
||||
noenter = 0;
|
||||
for (;;) {
|
||||
switch (g_gettype(p)) {
|
||||
case EORULE :
|
||||
return s;
|
||||
case TERM : {
|
||||
register p_term q;
|
||||
|
||||
q = g_getterm(p);
|
||||
if (flag == 0) {
|
||||
if (first(q->t_first,q->t_rule,0))/*nothing*/;
|
||||
}
|
||||
if (!noenter) s |= setunion(setp,q->t_first);
|
||||
p++;
|
||||
if (r_getkind(q) == STAR ||
|
||||
r_getkind(q) == OPT ||
|
||||
empty(q->t_rule)) continue;
|
||||
break; }
|
||||
case ALTERNATION : {
|
||||
register p_link l;
|
||||
|
||||
l = g_getlink(p);
|
||||
if (flag == 0) {
|
||||
if (first(l->l_symbs,l->l_rule,0))/*nothing*/;
|
||||
}
|
||||
if (noenter == 0) {
|
||||
s |= setunion(setp,l->l_symbs);
|
||||
}
|
||||
if (g_gettype(p+1) == EORULE) return s;
|
||||
}
|
||||
/* Fall Through */
|
||||
case ACTION :
|
||||
p++;
|
||||
continue;
|
||||
case LITERAL :
|
||||
case TERMINAL :
|
||||
if ((noenter == 0) && !IN(setp,g_getcont(p))) {
|
||||
s = 1;
|
||||
PUTIN(setp,g_getcont(p));
|
||||
}
|
||||
p++;
|
||||
break;
|
||||
case NONTERM : {
|
||||
register p_nont n;
|
||||
|
||||
n = &nonterms[g_getcont(p)];
|
||||
if (noenter == 0) {
|
||||
s |= setunion(setp,n->n_first);
|
||||
if (ntneeded) NTPUTIN(setp,g_getcont(p));
|
||||
}
|
||||
p++;
|
||||
if (n->n_flags & EMPTY) continue;
|
||||
break; }
|
||||
}
|
||||
if (flag == 0) {
|
||||
noenter = 1;
|
||||
continue;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC int
|
||||
nfollow(p) register p_nont p; {
|
||||
return follow(p->n_follow, p->n_rule);
|
||||
}
|
||||
|
||||
STATIC
|
||||
follow(setp,p) p_set setp; register p_gram p; {
|
||||
/*
|
||||
* setp is the follow set for the rule p.
|
||||
* Compute the follow sets in the rule p from this set.
|
||||
* Return 1 if a follow set of a nonterminal changed.
|
||||
*/
|
||||
register s; /* Will gather return value */
|
||||
|
||||
s = 0;
|
||||
for (;;) {
|
||||
switch (g_gettype(p)) {
|
||||
case EORULE :
|
||||
return s;
|
||||
case TERM : {
|
||||
register p_term q;
|
||||
|
||||
q = g_getterm(p);
|
||||
if (empty(p+1)) {
|
||||
/*
|
||||
* If what follows the term can be empty,
|
||||
* everything that can follow the whole
|
||||
* rule can also follow the term
|
||||
*/
|
||||
s |= setunion(q->t_follow,setp);
|
||||
}
|
||||
/*
|
||||
* Everything that can start the rest of the rule
|
||||
* can follow the term
|
||||
*/
|
||||
s |= first(q->t_follow,p+1,1);
|
||||
if (r_getkind(q) == STAR ||
|
||||
r_getkind(q) == PLUS ||
|
||||
r_getnum(q) ) {
|
||||
/*
|
||||
* If the term involves a repetition
|
||||
* of possibly more than one,
|
||||
* everything that can start the term
|
||||
* can also follow it.
|
||||
*/
|
||||
s |= follow(q->t_first,q->t_rule);
|
||||
}
|
||||
/*
|
||||
* Now propagate the set computed sofar
|
||||
*/
|
||||
s |= follow(q->t_follow, q->t_rule);
|
||||
break; }
|
||||
case ALTERNATION :
|
||||
/*
|
||||
* Just propagate setp
|
||||
*/
|
||||
s |= follow(setp,g_getlink(p)->l_rule);
|
||||
break;
|
||||
case NONTERM : {
|
||||
register p_nont n;
|
||||
|
||||
n = &nonterms[g_getcont(p)];
|
||||
s |= first(n->n_follow,p+1,1);
|
||||
if (empty(p+1)) {
|
||||
/*
|
||||
* If the rest of p can produce empty,
|
||||
* everything that follows p can follow
|
||||
* the nonterminal
|
||||
*/
|
||||
s |= setunion(n->n_follow,setp);
|
||||
}
|
||||
break; }
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
co_dirsymb(setp,p) p_set setp; register p_gram p; {
|
||||
/*
|
||||
* Walk the rule p, doing the work for alternations
|
||||
*/
|
||||
register p_gram s = 0;
|
||||
|
||||
for (;;) {
|
||||
switch (g_gettype(p)) {
|
||||
case EORULE :
|
||||
return;
|
||||
case TERM : {
|
||||
register p_term q;
|
||||
|
||||
q = g_getterm(p);
|
||||
co_dirsymb(q->t_follow,q->t_rule);
|
||||
break; }
|
||||
case ALTERNATION : {
|
||||
register p_link l;
|
||||
/*
|
||||
* Save first alternative
|
||||
*/
|
||||
if (!s) s = p;
|
||||
l = g_getlink(p);
|
||||
co_dirsymb(setp,l->l_rule);
|
||||
if (empty(l->l_rule)) {
|
||||
/*
|
||||
* If the rule can produce empty, everything
|
||||
* that follows it can also start it
|
||||
*/
|
||||
setunion(l->l_symbs,setp);
|
||||
}
|
||||
if (g_gettype(p+1) == EORULE) {
|
||||
/*
|
||||
* Every alternation is implemented as a
|
||||
* choice between two alternatives :
|
||||
* this one or one of the following.
|
||||
* The l_others set will contain the starters
|
||||
* of the other alternatives
|
||||
*/
|
||||
co_others(s);
|
||||
return;
|
||||
} }
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
co_others(p) register p_gram p; {
|
||||
/*
|
||||
* compute the l_others-sets for the list of alternatives
|
||||
* indicated by p
|
||||
*/
|
||||
register p_link l1,l2;
|
||||
|
||||
l1 = g_getlink(p);
|
||||
p++;
|
||||
l2 = g_getlink(p);
|
||||
setunion(l1->l_others,l2->l_symbs);
|
||||
if (g_gettype(p+1) != EORULE) {
|
||||
/*
|
||||
* First compute l2->l_others
|
||||
*/
|
||||
co_others(p);
|
||||
/*
|
||||
* and then l1->l_others
|
||||
*/
|
||||
setunion(l1->l_others,l2->l_others);
|
||||
}
|
||||
}
|
||||
|
||||
static p_length length;
|
||||
# define INFINITY 32767
|
||||
|
||||
STATIC
|
||||
ncomplength(p)
|
||||
register p_nont p;
|
||||
{
|
||||
register p_length pl = &length[p - nonterms];
|
||||
int x = pl->cnt;
|
||||
|
||||
pl->cnt = -1;
|
||||
complength(p->n_rule, pl);
|
||||
return pl->cnt < INFINITY && x == INFINITY;
|
||||
}
|
||||
|
||||
STATIC
|
||||
do_lengthcomp() {
|
||||
/*
|
||||
* Compute the minimum length of a terminal production for each
|
||||
* nonterminal.
|
||||
* This length consists of two fields: the number of terminals,
|
||||
* and a number that is composed of
|
||||
* - the number of this alternative
|
||||
* - a crude measure of the number of terms and nonterminals in the
|
||||
* production of this shortest string.
|
||||
*/
|
||||
register p_length pl;
|
||||
register p_nont p;
|
||||
p_mem alloc();
|
||||
|
||||
length = (p_length) alloc((unsigned) (nnonterms * sizeof(*length)));
|
||||
for (pl = &length[nnonterms-1]; pl >= length; pl--) {
|
||||
pl->val = pl->cnt = INFINITY;
|
||||
}
|
||||
|
||||
co_trans(ncomplength);
|
||||
|
||||
pl = length;
|
||||
for (p = nonterms; p < maxnt; p++, pl++) {
|
||||
if (pl->cnt == INFINITY) {
|
||||
p->n_flags |= RECURSIVE;
|
||||
}
|
||||
setdefaults(p->n_rule);
|
||||
}
|
||||
free ((p_mem) length);
|
||||
}
|
||||
|
||||
STATIC
|
||||
complength(p,le) register p_gram p; p_length le; {
|
||||
/*
|
||||
* Walk grammar rule p, computing minimum lengths
|
||||
*/
|
||||
register p_link l;
|
||||
register p_term q;
|
||||
t_length i;
|
||||
t_length X;
|
||||
int cnt = 0;
|
||||
|
||||
X.cnt = 0;
|
||||
X.val = 0;
|
||||
for (;;) {
|
||||
switch (g_gettype(p)) {
|
||||
case LITERAL :
|
||||
case TERMINAL :
|
||||
add(&X, 1, 0);
|
||||
break;
|
||||
case ALTERNATION :
|
||||
|
||||
X.cnt = INFINITY;
|
||||
X.val = INFINITY;
|
||||
while (g_gettype(p) != EORULE) {
|
||||
cnt++;
|
||||
l = g_getlink(p);
|
||||
complength(l->l_rule,&i);
|
||||
i.val += cnt;
|
||||
if (l->l_flag & DEF) {
|
||||
X = i;
|
||||
break;
|
||||
}
|
||||
if (compare(&i, &X) < 0) {
|
||||
X = i;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
/* Fall through */
|
||||
case EORULE :
|
||||
le->cnt = X.cnt;
|
||||
le->val = X.val;
|
||||
return;
|
||||
case TERM : {
|
||||
register int rep;
|
||||
|
||||
q = g_getterm(p);
|
||||
rep = r_getkind(q);
|
||||
X.val += 1;
|
||||
if ((q->t_flags&PERSISTENT) ||
|
||||
rep==FIXED || rep==PLUS) {
|
||||
complength(q->t_rule,&i);
|
||||
add(&X, i.cnt, i.val);
|
||||
if (rep == FIXED && r_getnum(q) > 0) {
|
||||
for (rep = r_getnum(q) - 1;
|
||||
rep > 0; rep--) {
|
||||
add(&X, i.cnt, i.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
break; }
|
||||
case NONTERM : {
|
||||
int nn = g_getcont(p);
|
||||
register p_length pl = &length[nn];
|
||||
int x = pl->cnt;
|
||||
|
||||
if (x == INFINITY) {
|
||||
pl->cnt = -1;
|
||||
complength(nonterms[nn].n_rule,pl);
|
||||
x = pl->cnt;
|
||||
}
|
||||
else if (x == -1) x = INFINITY;
|
||||
add(&X, x, pl->val);
|
||||
X.val += 1;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
add(a, c, v) register p_length a; {
|
||||
|
||||
if (a->cnt == INFINITY || c == INFINITY) {
|
||||
a->cnt = INFINITY;
|
||||
return;
|
||||
}
|
||||
a->val += v;
|
||||
a->cnt += c;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
compare(a, b) register p_length a, b; {
|
||||
if (a->cnt != b->cnt) return a->cnt - b->cnt;
|
||||
return a->val - b->val;
|
||||
}
|
||||
|
||||
STATIC
|
||||
setdefaults(p) register p_gram p; {
|
||||
for (;;) {
|
||||
switch(g_gettype(p)) {
|
||||
case EORULE:
|
||||
return;
|
||||
case TERM:
|
||||
setdefaults(g_getterm(p)->t_rule);
|
||||
break;
|
||||
case ALTERNATION: {
|
||||
register p_link l, l1;
|
||||
int temp = 0, temp1, cnt = 0;
|
||||
t_length count, i;
|
||||
|
||||
count.cnt = INFINITY;
|
||||
count.val = INFINITY;
|
||||
l1 = g_getlink(p);
|
||||
do {
|
||||
cnt++;
|
||||
l = g_getlink(p);
|
||||
complength(l->l_rule,&i);
|
||||
i.val += cnt;
|
||||
if (l->l_flag & DEF) temp = 1;
|
||||
temp1 = compare(&i, &count);
|
||||
if (temp1 < 0 ||
|
||||
(temp1 == 0 && l1->l_flag & AVOIDING)) {
|
||||
l1 = l;
|
||||
count = i;
|
||||
}
|
||||
setdefaults(l->l_rule);
|
||||
p++;
|
||||
} while (g_gettype(p) != EORULE);
|
||||
if (!temp) {
|
||||
/* No user specified default */
|
||||
l1->l_flag |= DEF;
|
||||
}
|
||||
return; }
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
do_contains(n) register p_nont n; {
|
||||
/*
|
||||
* Compute the total set of symbols that nonterminal n can
|
||||
* produce
|
||||
*/
|
||||
|
||||
if (n->n_contains == 0) {
|
||||
n->n_contains = get_set();
|
||||
contains(n->n_rule,n->n_contains);
|
||||
/*
|
||||
* If the rule can produce empty, delete all symbols that
|
||||
* can follow the rule as well as be in the rule.
|
||||
* This is needed because the contains-set may only contain
|
||||
* symbols that are guaranteed to be eaten by the rule!
|
||||
* Otherwise, the generated parser may loop forever
|
||||
*/
|
||||
if (n->n_flags & EMPTY) {
|
||||
setminus(n->n_contains,n->n_follow);
|
||||
}
|
||||
/*
|
||||
* But the symbols that can start the rule are always
|
||||
* eaten
|
||||
*/
|
||||
setunion(n->n_contains,n->n_first);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
contains(p,set) register p_gram p; register p_set set; {
|
||||
/*
|
||||
* Does the real computation of the contains-sets
|
||||
*/
|
||||
|
||||
for (;;) {
|
||||
switch (g_gettype(p)) {
|
||||
case EORULE :
|
||||
return;
|
||||
case TERM : {
|
||||
register p_term q;
|
||||
int rep;
|
||||
|
||||
q = g_getterm(p);
|
||||
rep = r_getkind(q);
|
||||
if ((q->t_flags & PERSISTENT) ||
|
||||
rep == PLUS || rep == FIXED) {
|
||||
/*
|
||||
* In these cases, the term belongs to the
|
||||
* continuation grammar.
|
||||
* Otherwise, q->t_contains is just
|
||||
* q->t_first
|
||||
*/
|
||||
if (!q->t_contains) {
|
||||
q->t_contains = get_set();
|
||||
}
|
||||
contains(q->t_rule,q->t_contains);
|
||||
if (rep != FIXED || empty(q->t_rule)) {
|
||||
setminus(q->t_contains,q->t_follow);
|
||||
}
|
||||
setunion(q->t_contains,q->t_first);
|
||||
} else {
|
||||
contains(q->t_rule, (p_set) 0);
|
||||
q->t_contains = q->t_first;
|
||||
}
|
||||
if (set) setunion(set,q->t_contains);
|
||||
break; }
|
||||
case NONTERM : {
|
||||
register p_nont n;
|
||||
|
||||
n = &nonterms[g_getcont(p)];
|
||||
do_contains(n);
|
||||
if (set) {
|
||||
setunion(set, n->n_contains);
|
||||
if (ntneeded) NTPUTIN(set, g_getcont(p));
|
||||
}
|
||||
break; }
|
||||
case ALTERNATION : {
|
||||
register p_link l;
|
||||
|
||||
l = g_getlink(p);
|
||||
contains(l->l_rule,
|
||||
(l->l_flag & DEF) ? set : (p_set) 0);
|
||||
break; }
|
||||
case LITERAL :
|
||||
case TERMINAL : {
|
||||
register hulp;
|
||||
|
||||
if (set) {
|
||||
hulp = g_getcont(p);
|
||||
assert(hulp < ntokens);
|
||||
PUTIN(set,hulp);
|
||||
}}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC int nsafes(p) register p_nont p; {
|
||||
int ch;
|
||||
register int i;
|
||||
|
||||
ch = 0;
|
||||
i = getntsafe(p);
|
||||
if (i != NOSAFETY) {
|
||||
i = do_safes(p->n_rule, i, &ch);
|
||||
if (i < SCANDONE) i = SCANDONE;
|
||||
/* After a nonterminal, we only know whether a scan was done
|
||||
or not
|
||||
*/
|
||||
if (getntout(p) != i) {
|
||||
ch = 1;
|
||||
setntout(p,i);
|
||||
}
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
do_safes(p,safe,ch) register p_gram p; register int *ch; {
|
||||
/*
|
||||
* Walk the grammar rule, doing the computation described in the
|
||||
* comment of the procedure above this one.
|
||||
*/
|
||||
int retval;
|
||||
|
||||
for (;;) {
|
||||
switch (g_gettype(p)) {
|
||||
case ACTION:
|
||||
p++;
|
||||
continue;
|
||||
case LITERAL:
|
||||
case TERMINAL:
|
||||
safe = NOSCANDONE;
|
||||
break;
|
||||
case TERM : {
|
||||
register p_term q;
|
||||
int i,rep;
|
||||
|
||||
q = g_getterm(p);
|
||||
i = r_getnum(q);
|
||||
rep = r_getkind(q);
|
||||
retval = do_safes(q->t_rule,
|
||||
t_safety(rep,i,q->t_flags&PERSISTENT,safe),ch);
|
||||
settout(q, retval);
|
||||
safe = t_after(rep, i, retval);
|
||||
break; }
|
||||
case ALTERNATION : {
|
||||
register p_link l;
|
||||
register int i;
|
||||
|
||||
retval = -1;
|
||||
while (g_gettype(p) == ALTERNATION) {
|
||||
l = g_getlink(p);
|
||||
if (safe > SAFE && (l->l_flag & DEF)) {
|
||||
i = do_safes(l->l_rule,SAFESCANDONE,ch);
|
||||
}
|
||||
else i = do_safes(l->l_rule,SAFE,ch);
|
||||
if (retval == -1) retval = i;
|
||||
else if (i != retval) {
|
||||
if (i == NOSCANDONE ||
|
||||
retval == NOSCANDONE) {
|
||||
retval = SCANDONE;
|
||||
}
|
||||
else if (i > retval) retval = i;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return retval; }
|
||||
case NONTERM : {
|
||||
register p_nont n;
|
||||
register int nsafe, osafe;
|
||||
|
||||
n = &nonterms[g_getcont(p)];
|
||||
nsafe = getntsafe(n);
|
||||
osafe = safe;
|
||||
safe = getntout(n);
|
||||
if (safe == NOSAFETY) safe = SCANDONE;
|
||||
if (osafe == nsafe) break;
|
||||
if (nsafe == NOSAFETY) {
|
||||
*ch = 1;
|
||||
setntsafe(n, osafe);
|
||||
break;
|
||||
}
|
||||
if (osafe == NOSCANDONE || nsafe == NOSCANDONE) {
|
||||
if (nsafe != SCANDONE) {
|
||||
*ch = 1;
|
||||
setntsafe(n, SCANDONE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (osafe > nsafe) {
|
||||
setntsafe(n, osafe);
|
||||
*ch = 1;
|
||||
}
|
||||
break; }
|
||||
case EORULE :
|
||||
return safe;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
t_safety(rep, count, persistent, safety) {
|
||||
|
||||
if (safety == NOSCANDONE) safety = SCANDONE;
|
||||
switch(rep) {
|
||||
default:
|
||||
assert(0);
|
||||
case OPT:
|
||||
if (!persistent || safety < SAFESCANDONE) return SAFE;
|
||||
return SAFESCANDONE;
|
||||
case STAR:
|
||||
if (persistent) return SAFESCANDONE;
|
||||
return SAFE;
|
||||
case PLUS:
|
||||
if (persistent) {
|
||||
if (safety > SAFESCANDONE) return safety;
|
||||
return SAFESCANDONE;
|
||||
}
|
||||
return safety;
|
||||
case FIXED:
|
||||
if (!count) return safety;
|
||||
return SCANDONE;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
t_after(rep, count, outsafety) {
|
||||
if (count == 0 && (rep == STAR || rep == PLUS)) {
|
||||
return SAFESCANDONE;
|
||||
}
|
||||
if (rep != FIXED) {
|
||||
if (outsafety <= SAFESCANDONE) return SAFESCANDONE;
|
||||
return SCANDONE;
|
||||
}
|
||||
return outsafety;
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
* Miscellanious constants and
|
||||
* some variables that are visible in more than one file
|
||||
*/
|
||||
|
||||
# define LTEXTSZ 256 /* Size of longest token */
|
||||
|
||||
/*
|
||||
* options for the identifier search routine
|
||||
*/
|
||||
|
||||
# define ENTERING 1
|
||||
# define BOTH 2
|
||||
|
||||
/*
|
||||
* Now for some declarations
|
||||
*/
|
||||
|
||||
extern char ltext[]; /* input buffer */
|
||||
extern int nnonterms; /* number of nonterminals */
|
||||
extern int ntokens; /* number of terminals */
|
||||
extern int nterms; /* number of terms */
|
||||
extern int nalts; /* number of alternatives */
|
||||
extern p_start start; /* will contain startsymbols */
|
||||
extern int linecount; /* line number */
|
||||
extern int assval; /* to create difference between literals
|
||||
* and other terminals
|
||||
*/
|
||||
extern p_nont nonterms; /* the nonterminal array */
|
||||
extern p_nont maxnt; /* is filled up until here */
|
||||
extern p_token tokens; /* the token array */
|
||||
extern p_token maxt; /* is filled up until here */
|
||||
extern int norder, torder;
|
||||
/* order of nonterminals in the grammar,
|
||||
* important because actions are copied to
|
||||
* a temporary file in the order in which they
|
||||
* were read
|
||||
*/
|
||||
extern string e_noopen; /* Error message string used often */
|
||||
extern int verbose; /* Level of verbosity */
|
||||
extern int wflag; /* warnings? */
|
||||
extern string lexical; /* name of lexical analyser */
|
||||
extern string prefix; /* prefix of externals */
|
||||
extern string onerror; /* name of user error handler */
|
||||
extern int ntneeded; /* ntneeded = 1 if nonterminals are included
|
||||
* in the sets.
|
||||
*/
|
||||
extern int ntprint; /* ntprint = 1 if they must be printed too in
|
||||
* the LL.output file (-x option)
|
||||
*/
|
||||
# ifndef NDEBUG
|
||||
extern int debug;
|
||||
# endif /* not NDEBUG */
|
||||
extern p_file files,pfile; /* pointers to file structure.
|
||||
* "files" points to the start of the
|
||||
* list */
|
||||
extern p_file maxfiles;
|
||||
extern string LLgenid; /* LLgen identification string */
|
||||
extern t_token lextoken; /* the current token */
|
||||
extern int nerrors;
|
||||
extern string rec_file, incl_file;
|
||||
extern int low_percentage, high_percentage;
|
||||
extern int min_cases_for_jmptable;
|
||||
extern int jmptable_option;
|
||||
extern int ansi_c;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,69 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* global.c
|
||||
* Contains declarations visible in several other source files
|
||||
*/
|
||||
|
||||
# include "types.h"
|
||||
# include "extern.h"
|
||||
# include "io.h"
|
||||
|
||||
# ifndef NORCSID
|
||||
static string rcsid4 = "$Id$";
|
||||
# endif
|
||||
|
||||
char ltext[LTEXTSZ];
|
||||
p_nont nonterms;
|
||||
p_nont maxnt;
|
||||
int nnonterms;
|
||||
p_token tokens;
|
||||
p_token maxt;
|
||||
int ntokens;
|
||||
int nterms, nalts;
|
||||
int norder, torder;
|
||||
p_start start;
|
||||
int linecount;
|
||||
int assval;
|
||||
FILE *fout;
|
||||
FILE *fpars;
|
||||
FILE *finput;
|
||||
FILE *fact;
|
||||
char f_pars[] = PARSERFILE;
|
||||
char f_temp[] = ACTFILE;
|
||||
char f_out[20];
|
||||
string f_input;
|
||||
char f_include[20];
|
||||
char f_rec[20];
|
||||
string e_noopen = "Cannot open %s";
|
||||
int verbose;
|
||||
int wflag;
|
||||
string lexical;
|
||||
string prefix;
|
||||
string onerror;
|
||||
int ntneeded;
|
||||
int ntprint;
|
||||
# ifndef NDEBUG
|
||||
int debug;
|
||||
#endif /* not NDEBUG */
|
||||
p_file files;
|
||||
p_file maxfiles;
|
||||
p_file pfile;
|
||||
string LLgenid = "/* LLgen generated code from source %s */\n";
|
||||
t_token lextoken;
|
||||
int nerrors;
|
||||
string rec_file, incl_file;
|
||||
int low_percentage = 10, high_percentage = 30;
|
||||
int min_cases_for_jmptable = 8;
|
||||
int jmptable_option;
|
||||
int ansi_c = 0;
|
||||
@@ -1,37 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
* Some important file names and variables
|
||||
*/
|
||||
|
||||
# include <stdio.h>
|
||||
|
||||
/* FILES */
|
||||
|
||||
# define OUTFILE "%s.output" /* -v option */
|
||||
# define PARSERFILE "xxxXXXXXX" /* This is what we want */
|
||||
# define ACTFILE "tempXXXXXX" /* temporary file to save actions */
|
||||
# define HFILE "%spars.h" /* file for "#define's " */
|
||||
# define RFILE "%spars.c" /* Error recovery */
|
||||
|
||||
extern FILE *finput;
|
||||
extern FILE *fpars;
|
||||
extern FILE *fact;
|
||||
extern FILE *fout;
|
||||
extern char f_pars[];
|
||||
extern char f_temp[];
|
||||
extern char f_out[];
|
||||
extern string f_input;
|
||||
extern char f_include[];
|
||||
extern char f_rec[];
|
||||
@@ -1,69 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* machdep.c
|
||||
* Machine dependant things
|
||||
*/
|
||||
|
||||
# include "types.h"
|
||||
|
||||
# ifndef NORCSID
|
||||
static string rcsid5 = "$Id$";
|
||||
# endif
|
||||
|
||||
/* In this file the following routines are defined: */
|
||||
extern UNLINK();
|
||||
extern RENAME();
|
||||
extern string libpath();
|
||||
|
||||
UNLINK(x) string x; {
|
||||
/* Must remove the file "x" */
|
||||
|
||||
#ifdef USE_SYS
|
||||
sys_remove(x); /* systemcall to remove file */
|
||||
#else
|
||||
unlink(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
RENAME(x,y) string x,y; {
|
||||
/* Must move the file "x" to the file "y" */
|
||||
|
||||
#ifdef USE_SYS
|
||||
if(! sys_rename(x,y)) fatal(1,"Cannot rename to %s",y);
|
||||
#else
|
||||
unlink(y);
|
||||
if (link(x,y) != 0) fatal(1,"Cannot rename to %s",y);
|
||||
unlink(x);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* to make it easier to patch ... */
|
||||
char libdir[256] = LIBDIR;
|
||||
|
||||
string
|
||||
libpath(s) string s; {
|
||||
/* Must deliver a full pathname to the library file "s" */
|
||||
|
||||
register string p;
|
||||
register length;
|
||||
p_mem alloc();
|
||||
string strcpy(), strcat();
|
||||
|
||||
length = strlen(libdir) + strlen(s) + 2;
|
||||
p = (string) alloc((unsigned) length);
|
||||
strcpy(p,libdir);
|
||||
strcat(p,"/");
|
||||
strcat(p,s);
|
||||
return p;
|
||||
}
|
||||
@@ -1,344 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* main.c
|
||||
* Contains main program, and some error message routines
|
||||
*/
|
||||
|
||||
# include "types.h"
|
||||
# include "io.h"
|
||||
# include "extern.h"
|
||||
# include "sets.h"
|
||||
# include "assert.h"
|
||||
|
||||
# ifndef NORCSID
|
||||
static string rcsid6 = "$Id$";
|
||||
# endif
|
||||
|
||||
/* In this file the following routines are defined: */
|
||||
extern int main();
|
||||
STATIC readgrammar();
|
||||
STATIC doparse();
|
||||
extern error();
|
||||
extern fatal();
|
||||
extern comfatal();
|
||||
extern copyfile();
|
||||
extern install();
|
||||
extern char *mktemp();
|
||||
extern char *sbrk();
|
||||
|
||||
main(argc,argv) register string argv[]; {
|
||||
register string arg;
|
||||
string libpath();
|
||||
char *beg_sbrk;
|
||||
|
||||
/* Initialize */
|
||||
|
||||
assval = 0400;
|
||||
/* read options */
|
||||
|
||||
while (argc >= 2 && (arg = argv[1], *arg == '-')) {
|
||||
while (*++arg) {
|
||||
switch(*arg) {
|
||||
case 'j':
|
||||
case 'J':
|
||||
jmptable_option = 1;
|
||||
if (*++arg)
|
||||
min_cases_for_jmptable = atoi(arg);
|
||||
break;
|
||||
case 'w':
|
||||
case 'W':
|
||||
wflag = 1;
|
||||
continue;
|
||||
case 'v':
|
||||
case 'V':
|
||||
verbose++;
|
||||
continue;
|
||||
case 'l':
|
||||
case 'L':
|
||||
low_percentage = atoi(++arg);
|
||||
break;
|
||||
case 'h':
|
||||
case 'H':
|
||||
high_percentage = atoi(++arg);
|
||||
break;
|
||||
# ifndef NDEBUG
|
||||
case 'd':
|
||||
case 'D':
|
||||
debug++;
|
||||
continue;
|
||||
case 'r':
|
||||
case 'R':
|
||||
if (rec_file) {
|
||||
fprintf(stderr,"duplicate -r flag\n");
|
||||
exit(1);
|
||||
}
|
||||
rec_file = ++arg;
|
||||
break;
|
||||
case 'i':
|
||||
case 'I':
|
||||
if (incl_file) {
|
||||
fprintf(stderr,"duplicate -i flag\n");
|
||||
exit(1);
|
||||
}
|
||||
incl_file = ++arg;
|
||||
break;
|
||||
#endif /* not NDEBUG */
|
||||
case 'x':
|
||||
case 'X':
|
||||
ntneeded = 1;
|
||||
ntprint = 1;
|
||||
continue;
|
||||
case 'a':
|
||||
case 'A':
|
||||
ansi_c = 1;
|
||||
continue;
|
||||
default:
|
||||
fprintf(stderr,"illegal option : %c\n",*arg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
argv++;
|
||||
argc--;
|
||||
}
|
||||
|
||||
if (verbose) beg_sbrk = sbrk(0);
|
||||
|
||||
/*
|
||||
* Now check wether the sets should include nonterminals
|
||||
*/
|
||||
if (verbose == 2) ntneeded = 1;
|
||||
/*
|
||||
* Initialise
|
||||
*/
|
||||
# ifndef NDEBUG
|
||||
if (!rec_file) {
|
||||
# endif
|
||||
rec_file = libpath("rec");
|
||||
# ifndef NDEBUG
|
||||
}
|
||||
if (!incl_file) {
|
||||
# endif
|
||||
incl_file = libpath("incl");
|
||||
# ifndef NDEBUG
|
||||
}
|
||||
# endif
|
||||
mktemp(f_temp);
|
||||
mktemp(f_pars);
|
||||
if ((fact = fopen(f_temp,"w")) == NULL) {
|
||||
fputs("Cannot create temporary\n",stderr);
|
||||
exit(1);
|
||||
}
|
||||
name_init();
|
||||
readgrammar(argc,argv);
|
||||
sprintf(f_out, OUTFILE, prefix ? prefix : "LL");
|
||||
|
||||
/* for the following two filenames only one L is used; historical
|
||||
reasons ...
|
||||
*/
|
||||
sprintf(f_include, HFILE, prefix ? prefix : "L");
|
||||
sprintf(f_rec, RFILE, prefix ? prefix : "L");
|
||||
setinit(ntneeded);
|
||||
maxnt = &nonterms[nnonterms];
|
||||
maxt = &tokens[ntokens];
|
||||
fclose(fact);
|
||||
/*
|
||||
* Now, the grammar is read. Do some computations
|
||||
*/
|
||||
co_reach(); /* Check for undefined and unreachable */
|
||||
if (nerrors) comfatal();
|
||||
do_compute();
|
||||
conflchecks();
|
||||
if (nerrors) comfatal();
|
||||
if (argc-- == 1) {
|
||||
fputs("No code generation for input from standard input\n",
|
||||
stderr);
|
||||
}
|
||||
else gencode(argc);
|
||||
UNLINK(f_temp);
|
||||
UNLINK(f_pars);
|
||||
if (verbose) {
|
||||
fprintf(stderr, "number of nonterminals: %d\n", nnonterms);
|
||||
fprintf(stderr, "number of tokens: %d\n", ntokens);
|
||||
fprintf(stderr, "number of term structures: %d\n", nterms);
|
||||
fprintf(stderr, "number of alternation structures: %d\n", nalts);
|
||||
fprintf(stderr, "total memory used: %ld\n", (long)(sbrk(0) - beg_sbrk));
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
STATIC
|
||||
readgrammar(argc,argv) char *argv[]; {
|
||||
/*
|
||||
* Do just what the name suggests : read the grammar
|
||||
*/
|
||||
register p_file p;
|
||||
p_mem alloc();
|
||||
|
||||
linecount = 0;
|
||||
f_input = "no filename";
|
||||
/*
|
||||
* Build the file structure
|
||||
*/
|
||||
files = p = (p_file) alloc((unsigned) (argc+1) * sizeof(t_file));
|
||||
if (argc-- == 1) {
|
||||
finput = stdin;
|
||||
f_input = "standard input";
|
||||
doparse(p++);
|
||||
} else {
|
||||
while (argc--) {
|
||||
if ((finput = fopen(f_input=argv[1],"r")) == NULL) {
|
||||
fatal(0,e_noopen,f_input);
|
||||
}
|
||||
doparse(p++);
|
||||
argv++;
|
||||
fclose(finput);
|
||||
}
|
||||
}
|
||||
maxfiles = p;
|
||||
if (! lexical) lexical = "yylex";
|
||||
/*
|
||||
* There must be a start symbol!
|
||||
*/
|
||||
if (start == 0) {
|
||||
fatal(linecount,"Missing %%start");
|
||||
}
|
||||
if (nerrors) comfatal();
|
||||
}
|
||||
|
||||
STATIC
|
||||
doparse(p) register p_file p; {
|
||||
|
||||
linecount = 0;
|
||||
p->f_name = f_input;
|
||||
p->f_firsts = 0;
|
||||
pfile = p;
|
||||
torder = -1;
|
||||
norder = -1;
|
||||
LLparse();
|
||||
p->f_nonterminals = norder;
|
||||
p->f_terminals = torder;
|
||||
}
|
||||
|
||||
/* VARARGS1 */
|
||||
error(lineno,s,t,u) string s,t,u; {
|
||||
/*
|
||||
* Just an error message
|
||||
*/
|
||||
|
||||
++nerrors;
|
||||
if (!lineno) lineno = 1;
|
||||
fprintf(stderr,"\"%s\", line %d: ",f_input, lineno);
|
||||
fprintf(stderr,s,t,u);
|
||||
fputs("\n",stderr);
|
||||
}
|
||||
|
||||
/* VARARGS1 */
|
||||
warning(lineno,s,t,u) string s,t,u; {
|
||||
/*
|
||||
* Just a warning
|
||||
*/
|
||||
|
||||
if (wflag) return;
|
||||
if (!lineno) lineno = 1;
|
||||
fprintf(stderr,"\"%s\", line %d: (Warning) ",f_input, lineno);
|
||||
fprintf(stderr,s,t,u);
|
||||
fputs("\n",stderr);
|
||||
}
|
||||
|
||||
/* VARARGS1 */
|
||||
fatal(lineno,s,t,u) string s,t,u; {
|
||||
/*
|
||||
* Fatal error
|
||||
*/
|
||||
error(lineno,s,t,u);
|
||||
comfatal();
|
||||
}
|
||||
|
||||
comfatal() {
|
||||
/*
|
||||
* Some common code for exit on errors
|
||||
*/
|
||||
if (fact != NULL) {
|
||||
fclose(fact);
|
||||
UNLINK(f_temp);
|
||||
}
|
||||
if (fpars != NULL) fclose(fpars);
|
||||
UNLINK(f_pars);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
copyfile(file) string file; {
|
||||
/*
|
||||
* Copies a file indicated by the parameter to filedescriptor fpars.
|
||||
*/
|
||||
register int c;
|
||||
register FILE *f;
|
||||
|
||||
if ((f = fopen(file,"r")) == NULL) {
|
||||
fatal(0,"Cannot open libraryfile, call an expert");
|
||||
}
|
||||
while ((c = getc(f)) != EOF) putc(c,fpars);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
install(target, source) string target, source; {
|
||||
/*
|
||||
* Copy the temporary file generated from source to target
|
||||
* if allowed (which means that the target must be generated
|
||||
* by LLgen from the source, or that the target is not present
|
||||
*/
|
||||
register int c1, c2;
|
||||
register FILE *f1, *f2;
|
||||
int cnt;
|
||||
|
||||
/*
|
||||
* First open temporary, generated for source
|
||||
*/
|
||||
if ((f1 = fopen(f_pars,"r")) == NULL) {
|
||||
fatal(0,e_noopen,f_pars);
|
||||
}
|
||||
/*
|
||||
* Now open target for reading
|
||||
*/
|
||||
if ((f2 = fopen(target,"r")) == NULL) {
|
||||
fclose(f1);
|
||||
RENAME(f_pars, target);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Compute length of LLgen identification string. The target must
|
||||
* start with that!
|
||||
*/
|
||||
cnt = strlen(LLgenid) + strlen(source) - 2;
|
||||
/*
|
||||
* Now compare the target with the temporary
|
||||
*/
|
||||
do {
|
||||
c1 = getc(f1);
|
||||
c2 = getc(f2);
|
||||
if (cnt >= 0) cnt--;
|
||||
} while (c1 == c2 && c1 != EOF);
|
||||
fclose(f1);
|
||||
fclose(f2);
|
||||
/*
|
||||
* Here, if c1 != c2 the target must be recreated
|
||||
*/
|
||||
if (c1 != c2) {
|
||||
if (cnt >= 0) {
|
||||
fatal(0,"%s : not a file generated by LLgen",target);
|
||||
}
|
||||
RENAME(f_pars,target);
|
||||
}
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* name.c
|
||||
* Defines the symboltable search routine, a name store routine and an
|
||||
* initialising routine.
|
||||
*/
|
||||
|
||||
# include "types.h"
|
||||
# include "extern.h"
|
||||
# include "assert.h"
|
||||
# include "io.h"
|
||||
|
||||
# ifndef NORCSID
|
||||
static string rcsid7 = "$Id$";
|
||||
# endif
|
||||
|
||||
# define HASHSIZE 128
|
||||
# define NMSIZ 2048 /* Room for names allocated NMSIZ bytes at a time */
|
||||
|
||||
static char *name, *maxname;
|
||||
static p_entry h_root[HASHSIZE]; /* hash table */
|
||||
static string e_literal = "Illegal literal";
|
||||
static p_entry entries, maxentries;
|
||||
static t_info token_info, nont_info;
|
||||
|
||||
/* Defined in this file are: */
|
||||
extern string store();
|
||||
extern name_init();
|
||||
STATIC int hash();
|
||||
STATIC p_entry newentry();
|
||||
extern p_gram search();
|
||||
|
||||
p_mem alloc();
|
||||
p_mem new_mem();
|
||||
|
||||
name_init() {
|
||||
token_info.i_esize = sizeof (t_token);
|
||||
token_info.i_incr = 50;
|
||||
nont_info.i_esize = sizeof (t_nont);
|
||||
nont_info.i_incr = 50;
|
||||
search(TERMINAL,"EOFILE",ENTERING);
|
||||
}
|
||||
|
||||
STATIC p_entry
|
||||
newentry(str, next) string str; p_entry next; {
|
||||
register p_entry p;
|
||||
|
||||
if ((p = entries) == maxentries) {
|
||||
p = (p_entry) alloc(50 * sizeof(t_entry));
|
||||
maxentries = p + 50;
|
||||
}
|
||||
entries = p + 1;
|
||||
p->h_name = str;
|
||||
p->h_next = next;
|
||||
p->h_type.g_lineno = linecount;
|
||||
return p;
|
||||
}
|
||||
|
||||
string
|
||||
store(s) string s; {
|
||||
/*
|
||||
* Store a string s in the name table
|
||||
*/
|
||||
register string s1, t ,u;
|
||||
|
||||
u = name;
|
||||
t = s;
|
||||
s1 = u;
|
||||
do {
|
||||
if (u >= maxname) {
|
||||
u = alloc(NMSIZ);
|
||||
maxname = u + NMSIZ;
|
||||
t = s;
|
||||
s1 = u;
|
||||
}
|
||||
*u++ = *t;
|
||||
} while (*t++);
|
||||
name = u;
|
||||
return s1;
|
||||
}
|
||||
|
||||
STATIC int
|
||||
hash(str) string str; {
|
||||
/*
|
||||
* Compute the hash for string str
|
||||
*/
|
||||
register int i;
|
||||
register string l;
|
||||
|
||||
l = str;
|
||||
i = 0;
|
||||
while (*l != '\0') i += *l++ & 0377;
|
||||
i += l - str;
|
||||
return i % HASHSIZE;
|
||||
}
|
||||
|
||||
p_gram
|
||||
search(type,str,option) register string str; {
|
||||
/*
|
||||
* Search for object str.
|
||||
* It has type UNKNOWN, LITERAL, TERMINAL or NONTERM.
|
||||
* option can be ENTERING or BOTH (also looking).
|
||||
*/
|
||||
register int val = 0;
|
||||
register p_entry p;
|
||||
register int i;
|
||||
int type1;
|
||||
|
||||
i = hash(str);
|
||||
/*
|
||||
* Walk hash chain
|
||||
*/
|
||||
for (p = h_root[i]; p != (p_entry) 0; p = p->h_next) {
|
||||
if(!strcmp(p->h_name,str)) {
|
||||
type1 = g_gettype(&(p->h_type));
|
||||
if (type1 != type) {
|
||||
if (type1 == LITERAL || type == LITERAL) {
|
||||
continue;
|
||||
}
|
||||
if (type == TERMINAL) {
|
||||
error(linecount,
|
||||
"%s: is already a nonterminal",
|
||||
str);
|
||||
continue;
|
||||
}
|
||||
else if (type == NONTERM) {
|
||||
error(linecount,
|
||||
"%s : is already a token",
|
||||
str);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (option==ENTERING) {
|
||||
error(linecount,
|
||||
"%s : is already defined",str);
|
||||
}
|
||||
p->h_type.g_lineno = linecount;
|
||||
return &(p->h_type);
|
||||
}
|
||||
}
|
||||
p = newentry(store(str), h_root[i]);
|
||||
h_root[i] = p;
|
||||
if (type == TERMINAL || type == LITERAL) {
|
||||
register p_token pt;
|
||||
|
||||
pt = (p_token) new_mem(&token_info);
|
||||
tokens = (p_token) token_info.i_ptr;
|
||||
pt->t_string = p->h_name;
|
||||
if (type == LITERAL) {
|
||||
if (str[0] == '\\') {
|
||||
/*
|
||||
* Handle escapes in literals
|
||||
*/
|
||||
if (str[2] == '\0') {
|
||||
switch(str[1]) {
|
||||
case 'n' :
|
||||
val = '\n';
|
||||
break;
|
||||
case 'r' :
|
||||
val = '\r';
|
||||
break;
|
||||
case 'b' :
|
||||
val = '\b';
|
||||
break;
|
||||
case 'f' :
|
||||
val = '\f';
|
||||
break;
|
||||
case 't' :
|
||||
val = '\t';
|
||||
break;
|
||||
case '\'':
|
||||
val = '\'';
|
||||
break;
|
||||
case '\\':
|
||||
val = '\\';
|
||||
break;
|
||||
default :
|
||||
error(linecount,e_literal);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Here, str[2] != '\0'
|
||||
*/
|
||||
if (str[1] > '3' || str[1] < '0' ||
|
||||
str[2] > '7' || str[2] < '0' ||
|
||||
str[3] > '7' || str[3] < '0' ||
|
||||
str[4] != '\0') error(linecount,e_literal);
|
||||
val = 64*str[1] - 73*'0' +
|
||||
8*str[2] + str[3];
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* No escape in literal
|
||||
*/
|
||||
if (str[1] == '\0') val = str[0];
|
||||
else error(linecount,e_literal);
|
||||
}
|
||||
pt->t_tokno = val;
|
||||
g_settype(&(p->h_type), LITERAL);
|
||||
} else {
|
||||
/*
|
||||
* Here, type = TERMINAL
|
||||
*/
|
||||
pt->t_tokno = assval++;
|
||||
g_settype(&(p->h_type), TERMINAL);
|
||||
}
|
||||
g_setcont(&(p->h_type), ntokens);
|
||||
ntokens++;
|
||||
return &(p->h_type);
|
||||
}
|
||||
/*
|
||||
* type == NONTERM || type == UNKNOWN
|
||||
* UNKNOWN and not yet declared means : NONTERM
|
||||
*/
|
||||
{
|
||||
register p_nont q;
|
||||
|
||||
q = (p_nont) new_mem(&nont_info);
|
||||
nonterms = (p_nont) nont_info.i_ptr;
|
||||
q->n_name = p->h_name;
|
||||
q->n_rule = 0;
|
||||
q->n_lineno = linecount;
|
||||
q->n_string = f_input;
|
||||
q->n_follow = 0;
|
||||
q->n_flags = 0;
|
||||
q->n_contains = 0;
|
||||
g_settype(&(p->h_type), NONTERM);
|
||||
g_setcont(&(p->h_type), nnonterms);
|
||||
g_setnpar(&(p->h_type), 0);
|
||||
nnonterms++;
|
||||
return &(p->h_type);
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
#PARAMS do not remove this line
|
||||
|
||||
SRC_DIR = $(SRC_HOME)/util/LLgen/src
|
||||
LIBDIR = $(TARGET_HOME)/lib/LLgen
|
||||
INCLUDES = -I$(SRC_DIR) -I.
|
||||
LIBDIRSTR = \"$(LIBDIR)\"
|
||||
DEFINES = -DNDEBUG
|
||||
CFLAGS = $(DEFINES) $(INCLUDES) $(COPTIONS)
|
||||
LDFLAGS=$(LDOPTIONS)
|
||||
LINTFLAGS=$(LINTOPTIONS) $(DEFINES) $(INCLUDES) -DNORCSID
|
||||
|
||||
LLOPT= # -vvv -x
|
||||
|
||||
OBJECTS = main.$(SUF) gencode.$(SUF) compute.$(SUF) LLgen.$(SUF) tokens.$(SUF) \
|
||||
check.$(SUF) reach.$(SUF) global.$(SUF) name.$(SUF) sets.$(SUF) \
|
||||
Lpars.$(SUF) alloc.$(SUF) machdep.$(SUF) cclass.$(SUF)
|
||||
CSRC = $(SRC_DIR)/main.c $(SRC_DIR)/gencode.c $(SRC_DIR)/compute.c \
|
||||
$(SRC_DIR)/check.c $(SRC_DIR)/reach.c $(SRC_DIR)/global.c \
|
||||
$(SRC_DIR)/name.c $(SRC_DIR)/sets.c $(SRC_DIR)/alloc.c \
|
||||
$(SRC_DIR)/machdep.c $(SRC_DIR)/cclass.c
|
||||
CFILES = LLgen.c tokens.c Lpars.c $(CSRC)
|
||||
GFILES = $(SRC_DIR)/tokens.g $(SRC_DIR)/LLgen.g
|
||||
FILES = $(SRC_DIR)/types.h $(SRC_DIR)/extern.h \
|
||||
$(SRC_DIR)/io.h $(SRC_DIR)/sets.h \
|
||||
$(GFILES) $(CSRC) $(SRC_DIR)/proto.make
|
||||
|
||||
all: parser
|
||||
@make LLgen "LDFLAGS=$(LDFLAGS)" "CC=$(CC)" "CFLAGS=$(CFLAGS)" "LIBDIR=$(LIBDIR)"
|
||||
|
||||
parser: $(GFILES)
|
||||
LLgen $(LLOPT) $(GFILES)
|
||||
@touch parser
|
||||
|
||||
first: firstparser
|
||||
@make LLgen "LDFLAGS=$(LDFLAGS)" "CC=$(CC)" "CFLAGS=$(CFLAGS)" "LIBDIR=$(LIBDIR)"
|
||||
|
||||
firstparser:
|
||||
cp $(SRC_DIR)/LLgen.c.dist LLgen.c
|
||||
cp $(SRC_DIR)/tokens.c.dist tokens.c
|
||||
cp $(SRC_DIR)/Lpars.c.dist Lpars.c
|
||||
cp $(SRC_DIR)/Lpars.h.dist Lpars.h
|
||||
@touch parser
|
||||
|
||||
LLgen: $(OBJECTS)
|
||||
$(CC) $(LDFLAGS) $(OBJECTS) $(TARGET_HOME)/modules/lib/libsystem.$(LIBSUF) -o LLgen
|
||||
|
||||
pr :
|
||||
@pr $(FILES) $(SRC_HOME)/util/LLgen/lib/rec $(SRC_HOME)/util/LLgen/lib/incl
|
||||
|
||||
lint: parser
|
||||
$(LINT) $(LINTFLAGS) -DLIBDIR=$(LIBDIRSTR) $(CFILES)
|
||||
|
||||
clean:
|
||||
-rm -f *.$(SUF) LL.temp LL.xxx LL.output LLgen LLgen.c tokens.c Lpars.[ch] parser
|
||||
|
||||
distr:
|
||||
-rm -f parser
|
||||
make parser
|
||||
cp Lpars.c $(SRC_DIR)/Lpars.c.dist
|
||||
cp Lpars.h $(SRC_DIR)/Lpars.h.dist
|
||||
cp LLgen.c $(SRC_DIR)/LLgen.c.dist
|
||||
cp tokens.c $(SRC_DIR)/tokens.c.dist
|
||||
|
||||
LLgen.$(SUF): LLgen.c
|
||||
$(CC) -c $(CFLAGS) LLgen.c
|
||||
LLgen.$(SUF): Lpars.h
|
||||
LLgen.$(SUF): $(SRC_DIR)/cclass.h
|
||||
LLgen.$(SUF): $(SRC_DIR)/extern.h
|
||||
LLgen.$(SUF): $(SRC_DIR)/io.h
|
||||
LLgen.$(SUF): $(SRC_DIR)/types.h
|
||||
|
||||
Lpars.$(SUF): Lpars.c
|
||||
$(CC) -c $(CFLAGS) Lpars.c
|
||||
Lpars.$(SUF): Lpars.h
|
||||
|
||||
alloc.$(SUF): $(SRC_DIR)/alloc.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/alloc.c
|
||||
alloc.$(SUF): $(SRC_DIR)/extern.h
|
||||
alloc.$(SUF): $(SRC_DIR)/types.h
|
||||
|
||||
cclass.$(SUF): $(SRC_DIR)/cclass.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/cclass.c
|
||||
cclass.$(SUF): $(SRC_DIR)/cclass.h
|
||||
|
||||
check.$(SUF): $(SRC_DIR)/check.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/check.c
|
||||
check.$(SUF): $(SRC_DIR)/extern.h
|
||||
check.$(SUF): $(SRC_DIR)/io.h
|
||||
check.$(SUF): $(SRC_DIR)/sets.h
|
||||
check.$(SUF): $(SRC_DIR)/types.h
|
||||
|
||||
compute.$(SUF): $(SRC_DIR)/compute.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/compute.c
|
||||
compute.$(SUF): $(SRC_DIR)/extern.h
|
||||
compute.$(SUF): $(SRC_DIR)/io.h
|
||||
compute.$(SUF): $(SRC_DIR)/sets.h
|
||||
compute.$(SUF): $(SRC_DIR)/types.h
|
||||
|
||||
gencode.$(SUF): $(SRC_DIR)/gencode.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/gencode.c
|
||||
gencode.$(SUF): $(SRC_DIR)/cclass.h
|
||||
gencode.$(SUF): $(SRC_DIR)/extern.h
|
||||
gencode.$(SUF): $(SRC_DIR)/io.h
|
||||
gencode.$(SUF): $(SRC_DIR)/sets.h
|
||||
gencode.$(SUF): $(SRC_DIR)/types.h
|
||||
|
||||
global.$(SUF): $(SRC_DIR)/global.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/global.c
|
||||
global.$(SUF): $(SRC_DIR)/extern.h
|
||||
global.$(SUF): $(SRC_DIR)/io.h
|
||||
global.$(SUF): $(SRC_DIR)/types.h
|
||||
|
||||
machdep.$(SUF): $(SRC_DIR)/machdep.c
|
||||
$(CC) -c $(CFLAGS) -DUSE_SYS -DLIBDIR=$(LIBDIRSTR) $(SRC_DIR)/machdep.c
|
||||
machdep.$(SUF): $(SRC_DIR)/types.h
|
||||
|
||||
main.$(SUF): $(SRC_DIR)/main.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/main.c
|
||||
main.$(SUF): $(SRC_DIR)/extern.h
|
||||
main.$(SUF): $(SRC_DIR)/io.h
|
||||
main.$(SUF): $(SRC_DIR)/sets.h
|
||||
main.$(SUF): $(SRC_DIR)/types.h
|
||||
|
||||
name.$(SUF): $(SRC_DIR)/name.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/name.c
|
||||
name.$(SUF): $(SRC_DIR)/extern.h
|
||||
name.$(SUF): $(SRC_DIR)/io.h
|
||||
name.$(SUF): $(SRC_DIR)/types.h
|
||||
|
||||
reach.$(SUF): $(SRC_DIR)/reach.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/reach.c
|
||||
reach.$(SUF): $(SRC_DIR)/extern.h
|
||||
reach.$(SUF): $(SRC_DIR)/io.h
|
||||
reach.$(SUF): $(SRC_DIR)/types.h
|
||||
|
||||
sets.$(SUF): $(SRC_DIR)/sets.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/sets.c
|
||||
sets.$(SUF): $(SRC_DIR)/extern.h
|
||||
sets.$(SUF): $(SRC_DIR)/sets.h
|
||||
sets.$(SUF): $(SRC_DIR)/types.h
|
||||
|
||||
tokens.$(SUF): tokens.c
|
||||
$(CC) -c $(CFLAGS) tokens.c
|
||||
tokens.$(SUF): Lpars.h
|
||||
tokens.$(SUF): $(SRC_DIR)/cclass.h
|
||||
tokens.$(SUF): $(SRC_DIR)/extern.h
|
||||
tokens.$(SUF): $(SRC_DIR)/io.h
|
||||
tokens.$(SUF): $(SRC_DIR)/types.h
|
||||
@@ -1,134 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* reach.c
|
||||
* Determine which nonterminals are reachable, and also check that they
|
||||
* are all defined.
|
||||
*/
|
||||
|
||||
# include "types.h"
|
||||
# include "extern.h"
|
||||
# include "io.h"
|
||||
# include "assert.h"
|
||||
|
||||
# ifndef NORCSID
|
||||
static string rcsid8 = "$Id$";
|
||||
# endif
|
||||
|
||||
/* In this file the following routines are defined: */
|
||||
extern co_reach();
|
||||
STATIC reachable();
|
||||
STATIC reachwalk();
|
||||
|
||||
co_reach() {
|
||||
/*
|
||||
* Check for undefined or unreachable nonterminals.
|
||||
*/
|
||||
register p_nont p;
|
||||
register p_token t;
|
||||
register p_start st;
|
||||
register p_file x;
|
||||
register int s;
|
||||
|
||||
/* Check for undefined nonterminals */
|
||||
for (p = nonterms; p < maxnt; p++) {
|
||||
if (! p->n_rule) { /* undefined */
|
||||
f_input = p->n_string;
|
||||
error(p->n_lineno,"Nonterminal %s not defined",
|
||||
p->n_name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk the grammar rules, starting with the startsymbols
|
||||
* Mark the nonterminals that are encountered with the flag
|
||||
* REACHABLE, and walk their rules, if not done before
|
||||
*/
|
||||
for (st = start; st; st = st->ff_next) {
|
||||
reachable(&nonterms[st->ff_nont]);
|
||||
}
|
||||
/*
|
||||
* Now check for unreachable nonterminals
|
||||
*/
|
||||
for (x = files; x < maxfiles; x++) {
|
||||
f_input = x->f_name;
|
||||
for (s = x->f_nonterminals; s != -1; s = p->n_next) {
|
||||
p = &nonterms[s];
|
||||
if (! (p->n_flags & REACHABLE)) {
|
||||
warning(p->n_lineno,"nonterminal %s unreachable",
|
||||
p->n_name);
|
||||
}
|
||||
}
|
||||
for (s = x->f_terminals; s != -1; s = t->t_next) {
|
||||
t = &tokens[s];
|
||||
if (! (t->t_flags & REACHABLE)) {
|
||||
warning(t->t_lineno,"terminal %s not used",
|
||||
t->t_string);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
reachable(p) register p_nont p; {
|
||||
/*
|
||||
* Enter the fact that p is reachable, and look for implications
|
||||
*/
|
||||
if (! (p->n_flags & REACHABLE)) {
|
||||
p->n_flags |= REACHABLE;
|
||||
/*
|
||||
* Now walk its grammar rule
|
||||
*/
|
||||
if (p->n_rule) reachwalk(p->n_rule);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
reachwalk(p) register p_gram p; {
|
||||
/*
|
||||
* Walk through rule p, looking for nonterminals.
|
||||
* The nonterminals found are entered as reachable
|
||||
*/
|
||||
|
||||
for (;;) {
|
||||
switch(g_gettype(p)) {
|
||||
case ALTERNATION :
|
||||
reachwalk(g_getlink(p)->l_rule);
|
||||
break;
|
||||
case TERM :
|
||||
reachwalk(g_getterm(p)->t_rule);
|
||||
break;
|
||||
case NONTERM : {
|
||||
register p_nont n = &nonterms[g_getcont(p)];
|
||||
|
||||
reachable(n);
|
||||
if (n->n_rule && g_gettype(n->n_rule) == EORULE &&
|
||||
! g_getnpar(p) && (getntparams(n) == 0)) {
|
||||
register p_gram np = p;
|
||||
do {
|
||||
*np = *(np + 1);
|
||||
np++;
|
||||
} while (g_gettype(np) != EORULE);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TERMINAL:
|
||||
tokens[g_getcont(p)].t_flags |= REACHABLE;
|
||||
break;
|
||||
case EORULE :
|
||||
return;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
}
|
||||
@@ -1,217 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* sets.c
|
||||
* Set manipulation and allocation routines.
|
||||
*/
|
||||
|
||||
# include "types.h"
|
||||
# include "extern.h"
|
||||
# include "sets.h"
|
||||
# include "assert.h"
|
||||
|
||||
# ifndef NORCSID
|
||||
static string rcsid9 = "$Id$";
|
||||
# endif
|
||||
|
||||
/* In this file the following routines are defined: */
|
||||
extern setinit();
|
||||
extern p_set setalloc();
|
||||
extern p_set get_set();
|
||||
extern int setunion();
|
||||
extern int setintersect();
|
||||
extern setminus();
|
||||
extern int setempty();
|
||||
extern int findindex();
|
||||
extern int setcount();
|
||||
|
||||
int nbytes;
|
||||
static int setsize;
|
||||
int tsetsize;
|
||||
p_set *setptr, *maxptr;
|
||||
static t_info set_info;
|
||||
p_mem alloc();
|
||||
|
||||
setinit(nt_needed) {
|
||||
/*
|
||||
* Initialises some variables needed for setcomputations
|
||||
*/
|
||||
register int bitset;
|
||||
|
||||
nbytes = NBYTES(ntokens);
|
||||
bitset = ALIGN(nbytes);
|
||||
tsetsize = NINTS(bitset);
|
||||
if (nt_needed) {
|
||||
/* nonterminals must be included in the sets */
|
||||
bitset += NBYTES(nnonterms);
|
||||
}
|
||||
setsize = NINTS(bitset);
|
||||
set_info.i_esize = sizeof(p_set);
|
||||
set_info.i_incr = 20;
|
||||
}
|
||||
|
||||
p_set
|
||||
get_set() {
|
||||
/*
|
||||
* Allocate a set that cannot be freed
|
||||
*/
|
||||
register p_set p, q;
|
||||
static p_set sets, maxsets;
|
||||
|
||||
if ((p = sets) >= maxsets) {
|
||||
q = p = (p_set) alloc((unsigned) (50*setsize*sizeof(*sets)));
|
||||
maxsets = p + 50 * setsize;
|
||||
do {
|
||||
*q++ = 0;
|
||||
} while (q < maxsets);
|
||||
}
|
||||
sets = p + setsize;;
|
||||
return p;
|
||||
}
|
||||
|
||||
p_set
|
||||
setalloc() {
|
||||
/*
|
||||
* Allocate a set which can later be freed.
|
||||
*/
|
||||
register p_set p;
|
||||
register int size = setsize;
|
||||
|
||||
p = (p_set) alloc((unsigned) (size * sizeof(*p))) + size;
|
||||
do {
|
||||
*--p = 0;
|
||||
} while (--size);
|
||||
return p;
|
||||
}
|
||||
|
||||
int
|
||||
setunion(a,b) register p_set a,b; {
|
||||
/*
|
||||
* a = a union b.
|
||||
* Return 1 if the set a changed
|
||||
*/
|
||||
register int i;
|
||||
register int j;
|
||||
register int nsub = 0;
|
||||
|
||||
i = setsize;
|
||||
do {
|
||||
*a = (j = *a) | *b++;
|
||||
if (*a++ != j) {
|
||||
nsub = 1;
|
||||
}
|
||||
} while (--i);
|
||||
return nsub;
|
||||
}
|
||||
|
||||
int
|
||||
setintersect(a,b) register p_set a,b; {
|
||||
/*
|
||||
* a = a intersect b.
|
||||
* return 1 if the result is empty
|
||||
*/
|
||||
register int i;
|
||||
register int nempty;
|
||||
|
||||
nempty = 1;
|
||||
i = setsize;
|
||||
do {
|
||||
if (*a++ &= *b++) nempty = 0;
|
||||
} while (--i);
|
||||
return nempty;
|
||||
}
|
||||
|
||||
setminus(a,b) register p_set a,b; {
|
||||
/*
|
||||
* a = a setminus b
|
||||
*/
|
||||
register int i;
|
||||
|
||||
i = setsize;
|
||||
do {
|
||||
*a++ &= ~(*b++);
|
||||
} while (--i);
|
||||
}
|
||||
|
||||
int
|
||||
setempty(p) register p_set p; {
|
||||
/*
|
||||
* Return 1 if the set p is empty
|
||||
*/
|
||||
register int i;
|
||||
|
||||
i = tsetsize;
|
||||
do {
|
||||
if (*p++) return 0;
|
||||
} while (--i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
findindex(set) p_set set; {
|
||||
/*
|
||||
* The set "set" will serve as a recovery set.
|
||||
* Search for it in the table. If not present, enter it.
|
||||
* Here is room for improvement. At the moment, the list of
|
||||
* sets is examined with linear search.
|
||||
*/
|
||||
register p_set *t;
|
||||
p_mem new_mem();
|
||||
register p_set a;
|
||||
register p_set b;
|
||||
register int i;
|
||||
int saved;
|
||||
|
||||
/*
|
||||
* First search for the set in the table
|
||||
*/
|
||||
for (t = setptr; t < maxptr; t++) {
|
||||
a = *t;
|
||||
b = set;
|
||||
i = tsetsize;
|
||||
do {
|
||||
if (*a++ != *b++) break;
|
||||
} while (--i);
|
||||
if (i) continue;
|
||||
/*
|
||||
* Here, the sets are equal.
|
||||
*/
|
||||
return nbytes * (t - setptr);
|
||||
}
|
||||
/*
|
||||
* Now check if the set consists of only one element.
|
||||
* It would be a waste to use a set for that
|
||||
*/
|
||||
if (setcount(set, &saved) == 1) return -(saved + 1);
|
||||
/*
|
||||
* If it does, return its number as a negative number.
|
||||
*/
|
||||
maxptr = (p_set *) new_mem(&set_info);
|
||||
setptr = (p_set *) set_info.i_ptr;
|
||||
*maxptr = setalloc();
|
||||
setunion(*maxptr, set);
|
||||
return nbytes * (maxptr++ - setptr);
|
||||
}
|
||||
|
||||
int
|
||||
setcount(set, saved) register p_set set; int *saved; {
|
||||
register int i, j;
|
||||
|
||||
for (j = 0, i = 0; i < ntokens; i++) {
|
||||
if (IN(set,i)) {
|
||||
j++;
|
||||
*saved = i;
|
||||
}
|
||||
}
|
||||
return j;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
* Some macros that deal with bitsets and their size
|
||||
*/
|
||||
|
||||
# define BITS (8 * sizeof (int))
|
||||
# define IN(a,i) ((a)[(i)/BITS] & (1<<((i) % BITS)))
|
||||
# define NTIN(a,i) ((a)[(i)/BITS+tsetsize]&(1<<((i)%BITS)))
|
||||
# define PUTIN(a,i) ((a)[(i)/BITS] |=(1<<((i) % BITS)))
|
||||
# define NTPUTIN(a,i) ((a)[(i)/BITS+tsetsize]|=(1<<((i)%BITS)))
|
||||
# define NBYTES(n) (((n) + 7) / 8)
|
||||
/*
|
||||
* The next two macros operate on byte counts!
|
||||
*/
|
||||
# define NINTS(n) (((n) + (int) (sizeof(int) - 1)) / (int) sizeof(int))
|
||||
# define ALIGN(n) (NINTS(n) * (int) sizeof (int))
|
||||
|
||||
extern int tsetsize;
|
||||
extern p_set *setptr, *maxptr;
|
||||
extern int nbytes;
|
||||
@@ -1,425 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* tokens.g
|
||||
* Defines the tokens for the grammar of LLgen.
|
||||
* The lexical analyser and LLmessage are also included here.
|
||||
*/
|
||||
|
||||
{
|
||||
# include "types.h"
|
||||
# include "io.h"
|
||||
# include "extern.h"
|
||||
# include "assert.h"
|
||||
# include "cclass.h"
|
||||
|
||||
# ifndef NORCSID
|
||||
static string rcsidc = "$Id$";
|
||||
# endif
|
||||
|
||||
/* Here are defined : */
|
||||
extern int scanner();
|
||||
extern LLmessage();
|
||||
extern int input();
|
||||
extern unput();
|
||||
extern skipcomment();
|
||||
# ifdef LINE_DIRECTIVE
|
||||
STATIC linedirective();
|
||||
# endif
|
||||
STATIC string cpy();
|
||||
STATIC string vallookup();
|
||||
}
|
||||
/* Classes */
|
||||
|
||||
%token C_IDENT ; /* lextoken.t_string contains the identifier read */
|
||||
%token C_NUMBER ; /* lextoken.t_num contains the number read */
|
||||
%token C_LITERAL ; /* lextoken.t_string contains the literal read */
|
||||
|
||||
/* Keywords */
|
||||
|
||||
%token C_TOKEN ;
|
||||
%token C_START ;
|
||||
%token C_IF ;
|
||||
%token C_WHILE ;
|
||||
%token C_PERSISTENT ;
|
||||
%token C_FIRST ;
|
||||
%token C_LEXICAL ;
|
||||
%token C_PREFIX ;
|
||||
%token C_ONERROR ;
|
||||
%token C_AVOID ;
|
||||
%token C_PREFER ;
|
||||
%token C_DEFAULT ;
|
||||
|
||||
%lexical scanner ;
|
||||
|
||||
{
|
||||
|
||||
/*
|
||||
* Structure for a keyword
|
||||
*/
|
||||
|
||||
typedef struct keyword {
|
||||
string w_word;
|
||||
int w_value;
|
||||
} t_keyw, *p_keyw;
|
||||
|
||||
/*
|
||||
* The list of keywords, the most often used keywords come first.
|
||||
* Linear search is used, as there are not many keywords
|
||||
*/
|
||||
|
||||
static t_keyw resword[] = {
|
||||
{ "token", C_TOKEN },
|
||||
{ "avoid", C_AVOID },
|
||||
{ "prefer", C_PREFER },
|
||||
{ "persistent", C_PERSISTENT },
|
||||
{ "default", C_DEFAULT },
|
||||
{ "if", C_IF },
|
||||
{ "while", C_WHILE },
|
||||
{ "first", C_FIRST },
|
||||
{ "start", C_START },
|
||||
{ "lexical", C_LEXICAL },
|
||||
{ "onerror", C_ONERROR },
|
||||
{ "prefix", C_PREFIX },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static t_token savedtok; /* to save lextoken in case of an insertion */
|
||||
# ifdef LINE_DIRECTIVE
|
||||
static int nostartline; /* = 0 if at the start of a line */
|
||||
# endif
|
||||
|
||||
scanner() {
|
||||
/*
|
||||
* Lexical analyser, what else
|
||||
*/
|
||||
register int ch; /* Current char */
|
||||
register char *p = ltext;
|
||||
int reserved = 0; /* reserved word? */
|
||||
char *max = <ext[LTEXTSZ - 1];
|
||||
|
||||
if (savedtok.t_tokno) {
|
||||
/* A token has been inserted.
|
||||
* Now deliver the last lextoken again
|
||||
*/
|
||||
lextoken = savedtok;
|
||||
savedtok.t_tokno = 0;
|
||||
return lextoken.t_tokno;
|
||||
}
|
||||
for (;;) {
|
||||
ch = input();
|
||||
if (ch == EOF) return ch;
|
||||
# ifdef LINE_DIRECTIVE
|
||||
if (ch == '#' && !nostartline) {
|
||||
linedirective();
|
||||
continue;
|
||||
}
|
||||
# endif
|
||||
switch(c_class[ch]) {
|
||||
case ISLIT :
|
||||
for (;;) {
|
||||
ch = input();
|
||||
if (ch == '\n' || ch == EOF) {
|
||||
error(linecount,"Missing '");
|
||||
break;
|
||||
}
|
||||
if (ch == '\'') break;
|
||||
if (ch == '\\') {
|
||||
*p++ = ch;
|
||||
ch = input();
|
||||
}
|
||||
*p++ = ch;
|
||||
if (p > max) p--;
|
||||
}
|
||||
*p = '\0';
|
||||
lextoken.t_string = ltext;
|
||||
return C_LITERAL;
|
||||
case ISCOM :
|
||||
skipcomment(0);
|
||||
/* Fall through */
|
||||
case ISSPA :
|
||||
continue;
|
||||
case ISDIG : {
|
||||
register i = 0;
|
||||
do {
|
||||
i = 10 * i + (ch - '0');
|
||||
ch= input();
|
||||
} while (c_class[ch] == ISDIG);
|
||||
lextoken.t_num = i;
|
||||
unput(ch);
|
||||
return C_NUMBER; }
|
||||
default:
|
||||
return ch;
|
||||
case ISKEY :
|
||||
reserved = 1;
|
||||
ch = input();
|
||||
/* Fall through */
|
||||
case ISLET :
|
||||
do {
|
||||
if (reserved && ch >= 'A' && ch <= 'Z') {
|
||||
ch += 'a' - 'A';
|
||||
}
|
||||
*p++ = ch;
|
||||
if (p > max) p--;
|
||||
ch = input();
|
||||
} while (c_class[ch] == ISDIG || c_class[ch] == ISLET);
|
||||
unput(ch);
|
||||
*p = '\0';
|
||||
if (reserved) { /*
|
||||
* Now search for the keyword
|
||||
*/
|
||||
register p_keyw w;
|
||||
|
||||
w = resword;
|
||||
while (w->w_word) {
|
||||
if (! strcmp(ltext,w->w_word)) {
|
||||
/*
|
||||
* Return token number.
|
||||
*/
|
||||
return w->w_value;
|
||||
}
|
||||
w++;
|
||||
}
|
||||
error(linecount,"Illegal reserved word");
|
||||
}
|
||||
lextoken.t_string = ltext;
|
||||
return C_IDENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int backupc; /* for unput() */
|
||||
static int nonline; /* = 1 if last char read was a newline */
|
||||
|
||||
input() {
|
||||
/*
|
||||
* Low level input routine, used by all other input routines
|
||||
*/
|
||||
register c;
|
||||
|
||||
if (c = backupc) {
|
||||
/* Last char was "unput()". Deliver it again
|
||||
*/
|
||||
backupc = 0;
|
||||
return c;
|
||||
}
|
||||
if ((c = getc(finput)) == EOF) return c;
|
||||
# ifdef LINE_DIRECTIVE
|
||||
nostartline = 1;
|
||||
# endif
|
||||
if (!nonline) {
|
||||
linecount++;
|
||||
# ifdef LINE_DIRECTIVE
|
||||
nostartline = 0;
|
||||
# endif
|
||||
nonline = 1;
|
||||
}
|
||||
if (c == '\n') nonline = 0;
|
||||
return c;
|
||||
}
|
||||
|
||||
unput(c) {
|
||||
/*
|
||||
* "unread" c
|
||||
*/
|
||||
backupc = c;
|
||||
}
|
||||
|
||||
skipcomment(flag) {
|
||||
/*
|
||||
* Skip comment. If flag != 0, the comment is inside a fragment
|
||||
* of C-code, so keep it.
|
||||
*/
|
||||
register int ch;
|
||||
int saved; /* line count on which comment starts */
|
||||
|
||||
saved = linecount;
|
||||
if (input() != '*') error(linecount,"Illegal comment");
|
||||
if (flag) putc('*', fact);
|
||||
do {
|
||||
ch = input();
|
||||
if (flag) putc(ch, fact);
|
||||
while (ch == '*') {
|
||||
ch = input();
|
||||
if (flag) putc(ch, fact);
|
||||
if (ch == '/') return;
|
||||
}
|
||||
} while (ch != EOF);
|
||||
error(saved,"Comment does not terminate");
|
||||
}
|
||||
|
||||
# ifdef LINE_DIRECTIVE
|
||||
STATIC
|
||||
linedirective() {
|
||||
/*
|
||||
* Read a line directive
|
||||
*/
|
||||
register int ch;
|
||||
register int i;
|
||||
string s_error = "Illegal line directive";
|
||||
string store();
|
||||
register string c;
|
||||
|
||||
do { /*
|
||||
* Skip to next digit
|
||||
* Do not skip newlines
|
||||
*/
|
||||
ch = input();
|
||||
} while (ch != '\n' && c_class[ch] != ISDIG);
|
||||
if (ch == '\n') {
|
||||
error(linecount,s_error);
|
||||
return;
|
||||
}
|
||||
i = 0;
|
||||
do {
|
||||
i = i*10 + (ch - '0');
|
||||
ch = input();
|
||||
} while (c_class[ch] == ISDIG);
|
||||
while (ch != '\n' && ch != '"') ch = input();
|
||||
if (ch == '"') {
|
||||
c = ltext;
|
||||
do {
|
||||
*c++ = ch = input();
|
||||
} while (ch != '"' && ch != '\n');
|
||||
if (ch == '\n') {
|
||||
error(linecount,s_error);
|
||||
return;
|
||||
}
|
||||
*--c = '\0';
|
||||
do {
|
||||
ch = input();
|
||||
} while (ch != '\n');
|
||||
/*
|
||||
* Remember the file name
|
||||
*/
|
||||
if (strcmp(f_input,ltext)) f_input = store(ltext);
|
||||
}
|
||||
linecount = i;
|
||||
}
|
||||
# endif
|
||||
|
||||
STATIC string
|
||||
vallookup(s) {
|
||||
/*
|
||||
* Look up the keyword that has token number s
|
||||
*/
|
||||
register p_keyw p = resword;
|
||||
|
||||
while (p->w_value) {
|
||||
if (p->w_value == s) return p->w_word;
|
||||
p++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC string
|
||||
cpy(s,p,inserted) register string p; {
|
||||
/*
|
||||
* Create a piece of error message for token s and put it at p.
|
||||
* inserted = 0 if the token s was deleted (in which case we have
|
||||
* attributes), else it was inserted
|
||||
*/
|
||||
register string t = 0;
|
||||
|
||||
switch(s) {
|
||||
case C_IDENT :
|
||||
if (!inserted) t = lextoken.t_string;
|
||||
else t = "identifier";
|
||||
break;
|
||||
case C_NUMBER :
|
||||
t = "number";
|
||||
break;
|
||||
case C_LITERAL :
|
||||
if (!inserted) {
|
||||
*p++ = '\'';
|
||||
t = lextoken.t_string;
|
||||
break;
|
||||
}
|
||||
t = "literal";
|
||||
break;
|
||||
case EOFILE :
|
||||
t = "endoffile";
|
||||
break;
|
||||
}
|
||||
if (!t && (t = vallookup(s))) {
|
||||
*p++ = '%';
|
||||
}
|
||||
if (t) { /*
|
||||
* We have a string for the token. Copy it
|
||||
*/
|
||||
while (*t) *p++ = *t++;
|
||||
if (s == C_LITERAL && !inserted) {
|
||||
*p++ = '\'';
|
||||
}
|
||||
return p;
|
||||
}
|
||||
/*
|
||||
* The token is a literal
|
||||
*/
|
||||
*p++ = '\'';
|
||||
if (s >= 040 && s <= 0176) *p++ = s;
|
||||
else {
|
||||
*p++ = '\\';
|
||||
switch(s) {
|
||||
case '\b' : *p++ = 'b'; break;
|
||||
case '\f' : *p++ = 'f'; break;
|
||||
case '\n' : *p++ = 'n'; break;
|
||||
case '\r' : *p++ = 'r'; break;
|
||||
case '\t' : *p++ = 't'; break;
|
||||
default : *p++='0'+((s&0377)>>6); *p++='0'+((s>>3)&07);
|
||||
*p++='0'+(s&07);
|
||||
}
|
||||
}
|
||||
*p++ = '\'';
|
||||
return p;
|
||||
}
|
||||
|
||||
LLmessage(d) {
|
||||
/*
|
||||
* d is either 0, in which case the current token has been deleted,
|
||||
* or non-zero, in which case it represents a token that is inserted
|
||||
* before the current token
|
||||
*/
|
||||
register string s,t;
|
||||
char buf[128];
|
||||
|
||||
nerrors++;
|
||||
s = buf;
|
||||
if (d == 0) {
|
||||
s = cpy(LLsymb,s,0);
|
||||
t = " deleted";
|
||||
do *s++ = *t; while (*t++);
|
||||
} else {
|
||||
s = cpy(d,s,1);
|
||||
t = " inserted in front of ";
|
||||
do *s++ = *t++; while (*t);
|
||||
s = cpy(LLsymb,s,0);
|
||||
*s = '\0';
|
||||
}
|
||||
error(linecount, "%s", buf);
|
||||
/* Don't change this line to
|
||||
* error(linecount, buf).
|
||||
* The string in "buf" might contain '%' ...
|
||||
*/
|
||||
if (d) { /*
|
||||
* Save the current token and make up some
|
||||
* attributes for the inserted token
|
||||
*/
|
||||
savedtok = lextoken;
|
||||
savedtok.t_tokno = LLsymb;
|
||||
if (d == C_IDENT) lextoken.t_string = "dummy_identifier";
|
||||
else if (d == C_LITERAL) lextoken.t_string = "dummy_literal";
|
||||
else if (d == C_NUMBER) lextoken.t_num = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
*
|
||||
* This product is part of the Amsterdam Compiler Kit.
|
||||
*
|
||||
* Permission to use, sell, duplicate or disclose this software must be
|
||||
* obtained in writing. Requests for such permissions may be sent to
|
||||
*
|
||||
* Dr. Andrew S. Tanenbaum
|
||||
* Wiskundig Seminarium
|
||||
* Vrije Universiteit
|
||||
* Postbox 7161
|
||||
* 1007 MC Amsterdam
|
||||
* The Netherlands
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* tunable.h $Header$
|
||||
* Tunable constants
|
||||
*/
|
||||
|
||||
# define LTEXTSZ 51 /* size of token */
|
||||
@@ -1,249 +0,0 @@
|
||||
/* Copyright (c) 1991 by the Vrije Universiteit, Amsterdam, the Netherlands.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
/*
|
||||
* L L G E N
|
||||
*
|
||||
* An Extended LL(1) Parser Generator
|
||||
*
|
||||
* Author : Ceriel J.H. Jacobs
|
||||
*/
|
||||
|
||||
/*
|
||||
* $Id$
|
||||
* Type and structure definitions
|
||||
*/
|
||||
|
||||
typedef int *p_set; /* pointer to bitset */
|
||||
typedef char *p_mem; /* pointer to some core */
|
||||
typedef char *string;
|
||||
|
||||
/*
|
||||
* structure for a token
|
||||
*/
|
||||
typedef struct token {
|
||||
int t_tokno; /* Lexical token number */
|
||||
union {
|
||||
string t_s; /* Attribute is either a string or */
|
||||
int t_v; /* an integer */
|
||||
} t_x;
|
||||
# define t_string t_x.t_s
|
||||
# define t_num t_x.t_v
|
||||
int t_flags;
|
||||
int t_next;
|
||||
int t_lineno;
|
||||
} t_token, *p_token;
|
||||
|
||||
/*
|
||||
* structure for the grammar elements
|
||||
*/
|
||||
typedef struct gram {
|
||||
short x; /* for lay-out see comment below */
|
||||
short g_lineno; /* element found on this line number */
|
||||
union {
|
||||
int g_index;
|
||||
struct term * g_term;
|
||||
struct link * g_link;
|
||||
} g_i;
|
||||
} t_gram,*p_gram;
|
||||
|
||||
/*
|
||||
* Layout of the field x:
|
||||
*
|
||||
* 15 ....... 7 6 ........ 3 2 .... 0
|
||||
* -----------------------------------
|
||||
* | unused | | nparams | | type |
|
||||
* -----------------------------------
|
||||
*/
|
||||
# define EORULE 00 /* End of (sub)rule */
|
||||
# define ACTION 01 /* Imbedded action */
|
||||
# define NONTERM 02 /* A nonterminal */
|
||||
# define TERMINAL 03 /* A terminal */
|
||||
# define TERM 04 /* Something between square brackets */
|
||||
# define ALTERNATION 05 /* Alternation (|) */
|
||||
# define LITERAL 06 /* Also a terminal */
|
||||
|
||||
/*
|
||||
* Access macros for the x-field of a grammar element
|
||||
*/
|
||||
# define g_gettype(p) ((p)->x&07)
|
||||
# define g_getcont(p) ((p)->g_i.g_index)
|
||||
# define g_getterm(p) ((p)->g_i.g_term)
|
||||
# define g_getlink(p) ((p)->g_i.g_link)
|
||||
# define g_getnpar(p) (((p)->x>>3)&017)
|
||||
# define g_settype(p,s) { assert(((unsigned)(s))<=07);(p)->x=((p)->x&~07)|(s);}
|
||||
# define g_setcont(p,s) ((p)->g_i.g_index=(s))
|
||||
# define g_setterm(p,s) ((p)->g_i.g_term = (s))
|
||||
# define g_setlink(p,s) ((p)->g_i.g_link = (s))
|
||||
# define g_setnpar(p,s) { assert(((unsigned)(s))<=017);(p)->x=((p)->x&~0170)|((s)<<3);}
|
||||
|
||||
/*
|
||||
* Some constants to communicate with the symbol table search routine
|
||||
*/
|
||||
# define UNKNOWN 00 /* Not equal to NONTERM, TERMINAL or LITERAL */
|
||||
|
||||
/*
|
||||
* Some constants for safety
|
||||
*/
|
||||
# define SAFE 0 /* Indicates that a scan is done, and that the
|
||||
* token is correct
|
||||
*/
|
||||
# define SAFESCANDONE 1 /* Indicates that a scan is done, and that the
|
||||
* token will not be skipped
|
||||
*/
|
||||
# define SCANDONE 2 /* Indicates that a scan is done */
|
||||
# define NOSCANDONE 3 /* Indicates that no scan is done */
|
||||
# define NOSAFETY 4 /* Safety not yet computed */
|
||||
|
||||
/*
|
||||
* nonterminal structure
|
||||
*/
|
||||
typedef struct {
|
||||
short n_flags; /* low order four bits are reserved
|
||||
* the parameter count
|
||||
*/
|
||||
# define getntparams(p) ((p)->n_flags&017)
|
||||
# define setntparams(p,i) {assert(((unsigned)(i))<=017);(p)->n_flags&=~017;(p)->n_flags|=(i);}
|
||||
# define GENSTATIC 01000 /* set if routine can be made static */
|
||||
# define RECURSIVE 02000 /* Set if the default rule is recursive */
|
||||
# define PARAMS 04000 /* tells if a nonterminal has parameters */
|
||||
# define EMPTY 010000 /* tells if a nonterminal produces empty */
|
||||
# define LOCALS 020000 /* local declarations ? */
|
||||
# define REACHABLE 040000 /* can this nonterminal be reached ? */
|
||||
# define VERBOSE 0100000 /* Set if in LL.output file */
|
||||
char n_insafety;
|
||||
char n_outsafety;
|
||||
# define getntsafe(p) ((p)->n_insafety)
|
||||
# define setntsafe(p,i) {assert(((unsigned)(i))<=NOSAFETY);(p)->n_insafety=(i);}
|
||||
# define getntout(p) ((p)->n_outsafety)
|
||||
# define setntout(p,i) {assert(((unsigned)(i))<=NOSAFETY);(p)->n_outsafety=(i);}
|
||||
short n_count; /* pieces of code before this rule */
|
||||
short n_lineno; /* declared on line ... */
|
||||
p_gram n_rule; /* pointer to right hand side of rule */
|
||||
union {
|
||||
p_set n_f; /* ptr to "first" set */
|
||||
string n_s; /* If this nonterminal is not declared,
|
||||
* This field indicates the filename in
|
||||
* which it occurred
|
||||
*/
|
||||
} n_x;
|
||||
# define n_first n_x.n_f
|
||||
# define n_string n_x.n_s
|
||||
p_set n_follow; /* pointer to the "follow" set */
|
||||
p_set n_contains; /* pointer to symbols that can be produced */
|
||||
string n_name; /* name of nonterminal */
|
||||
int n_next; /* index of next nonterminal */
|
||||
long n_off; /* index of parameters in action file */
|
||||
} t_nont, *p_nont;
|
||||
|
||||
/*
|
||||
* hash table structure
|
||||
*/
|
||||
typedef struct h_entry {
|
||||
string h_name; /* pointer to name */
|
||||
t_gram h_type; /* Type and index */
|
||||
struct h_entry *h_next; /* next in hash chain */
|
||||
} t_entry, *p_entry;
|
||||
|
||||
/*
|
||||
* link structure to link alternations
|
||||
*/
|
||||
typedef struct link {
|
||||
unsigned int l_flag;
|
||||
# define COND 01 /* Set if this alternative has a %if */
|
||||
# define DEF 02 /* This alternative is default */
|
||||
# define PREFERING 010 /* %prefer */
|
||||
# define AVOIDING 020 /* %avoid */
|
||||
# define NOCONF 01000 /* Set if there is a resolver without
|
||||
* conflict
|
||||
*/
|
||||
p_gram l_rule; /* pointer to this rule */
|
||||
p_set l_symbs; /* set, when to take this rule */
|
||||
p_set l_others; /* set, when to take another rule */
|
||||
} t_link, *p_link;
|
||||
|
||||
/*
|
||||
* Structure for a repitition specification
|
||||
*/
|
||||
typedef short t_reps,*p_reps;
|
||||
|
||||
# define FIXED 00 /* a fixed number */
|
||||
# define STAR 01 /* 0 or more times */
|
||||
# define PLUS 02 /* 1 or more times */
|
||||
# define OPT 03 /* 0 or 1 times */
|
||||
|
||||
/*
|
||||
* Access macros for repitition in term
|
||||
*/
|
||||
# define r_getkind(q) ((q)->t_repeats&03)
|
||||
# define r_getnum(q) (((q)->t_repeats>>2)&037777)
|
||||
# define r_setkind(q,s) { assert(((unsigned)(s))<=03);(q)->t_repeats=((q)->t_repeats&0177774)|(s);}
|
||||
# define r_setnum(q,s) { assert(((unsigned)(s))<=037777);(q)->t_repeats=((q)->t_repeats&03)|((s)<<2);}
|
||||
|
||||
/*
|
||||
* header structure for a term
|
||||
*/
|
||||
typedef struct term {
|
||||
t_reps t_repeats;
|
||||
short t_flags; /* Low order three bits for safety */
|
||||
# define gettout(q) ((q)->t_flags&07)
|
||||
# define settout(q,i) {assert(((unsigned)(i))<=NOSAFETY);(q)->t_flags&=~07;(q)->t_flags|=i;}
|
||||
# define PERSISTENT 010 /* Set if this term has %persistent */
|
||||
# define RESOLVER 020 /* Set if this term has %while */
|
||||
# define EMPTYFIRST 0100 /* Error, empty first */
|
||||
# define EMPTYTERM 0200 /* Error, term can produce empty */
|
||||
/* # define NOCONF 01000 see link structure */
|
||||
|
||||
p_gram t_rule; /* pointer to this term */
|
||||
p_set t_follow; /* set of followers */
|
||||
p_set t_first; /* set of firsts */
|
||||
p_set t_contains; /* contains set */
|
||||
} t_term, *p_term;
|
||||
|
||||
/*
|
||||
* structure for firstmacros list
|
||||
*/
|
||||
typedef struct ff_firsts {
|
||||
string ff_name; /* Name of the macro */
|
||||
int ff_nont; /* for this nonterminal */
|
||||
struct ff_firsts *ff_next;
|
||||
} t_first, *p_first;
|
||||
|
||||
/*
|
||||
* structure for start symbol list
|
||||
*/
|
||||
typedef t_first t_start;
|
||||
typedef p_first p_start;
|
||||
|
||||
/*
|
||||
* structure for file names and info
|
||||
*/
|
||||
typedef struct f_file {
|
||||
string f_name; /* File name */
|
||||
p_first f_firsts; /* ptr to list of firstmacros that must be
|
||||
* generated in the target file for this
|
||||
* grammar file
|
||||
*/
|
||||
int f_nonterminals; /* list of nonterminals in this file */
|
||||
int f_terminals; /* list of terminals in this file */
|
||||
p_set f_used; /* set of nonterminals used in this file */
|
||||
} t_file, *p_file;
|
||||
|
||||
typedef struct info_alloc {
|
||||
/*
|
||||
* Structure used for dynamically growing arrays
|
||||
*/
|
||||
unsigned i_size; /* Size of the array */
|
||||
unsigned i_esize; /* Size of an element */
|
||||
unsigned i_incr; /* When filled, add room for i_incr elements */
|
||||
p_mem i_ptr; /* ptr to base of array */
|
||||
p_mem i_max; /* ptr to first free */
|
||||
p_mem i_top; /* ptr to top of array */
|
||||
} t_info, *p_info;
|
||||
|
||||
# ifdef NDEBUG
|
||||
# define STATIC static
|
||||
# else /* not NDEBUG */
|
||||
# define STATIC extern
|
||||
# endif /* not NDEBUG */
|
||||
@@ -1,20 +0,0 @@
|
||||
proto.make
|
||||
ack.h
|
||||
data.c
|
||||
data.h
|
||||
dmach.h
|
||||
files.c
|
||||
grows.c
|
||||
grows.h
|
||||
list.c
|
||||
list.h
|
||||
main.c
|
||||
mktables.c
|
||||
rmach.c
|
||||
run.c
|
||||
scan.c
|
||||
svars.c
|
||||
trans.c
|
||||
trans.h
|
||||
util.c
|
||||
ack.1.X
|
||||
@@ -1,75 +0,0 @@
|
||||
# $Header$
|
||||
EMHOME=../..
|
||||
HFILES=ack.h list.h trans.h data.h dmach.h grows.h
|
||||
DSRC=list.c data.c main.c scan.c svars.c trans.c util.c rmach.c run.c grows.c\
|
||||
files.c
|
||||
ISRC=dmach.c intable.c
|
||||
OBJ=list.o data.o main.o scan.o svars.o trans.o util.o rmach.o run.o \
|
||||
dmach.o intable.o grows.o files.o
|
||||
ACKDIR=$(EMHOME)/lib
|
||||
FE=fe
|
||||
INTABLES=pdp
|
||||
LNTABLES=acc apc abc ocm m2 vax4 i86 i386 m68k2 m68k4 pmds pmds4 mantra \
|
||||
m68020 z8000 em22 em24 em44 6500 6800 6805 6809 i80 ns s2650 z80 \
|
||||
sun3 sun2 xenix3 minix minixST
|
||||
INCLUDES=-I$(EMHOME)/h
|
||||
CFLAGS=-O $(INCLUDES)
|
||||
LDFLAGS=
|
||||
BINDIR=$(EMHOME)/bin
|
||||
MANDIR=$(EMHOME)/man
|
||||
MODDIR=$(EMHOME)/modules/lib
|
||||
|
||||
head: ack ack.1
|
||||
|
||||
install: ack ack.1
|
||||
rm -f $(BINDIR)/ack
|
||||
cp ack $(BINDIR)/ack
|
||||
-cd $(BINDIR) ; \
|
||||
for i in $(INTABLES) $(LNTABLES) ; do rm -f $$i ; ln ack $$i ; done
|
||||
rm -f $(MANDIR)/ack.1
|
||||
cp ack.1 $(MANDIR)/ack.1
|
||||
|
||||
cmp: ack ack.1
|
||||
-cmp ack $(BINDIR)/ack
|
||||
-cmp ack.1 $(MANDIR)/ack.1
|
||||
|
||||
ack.1: ack.1.X
|
||||
-sh -c 'tbl < ack.1.X > ack.1'
|
||||
-sh -c 'if test -s ack.1 ; then : ; else cp ack.1.X ack.1 ; fi'
|
||||
|
||||
clean:
|
||||
-rm -f *.old *.o ack ack.1
|
||||
|
||||
ack: $(OBJ)
|
||||
$(CC) $(LDFLAGS) -o ack $(OBJ) $(MODDIR)/libstring.a
|
||||
|
||||
grows.o files.o list.o run.o \
|
||||
data.o main.o scan.o trans.o rmach.o util.o : ack.h list.h
|
||||
|
||||
files.o data.o main.o scan.o run.o trans.o rmach.o: trans.h data.h
|
||||
|
||||
files.o rmach.o trans.o grows.c : grows.h
|
||||
|
||||
rmach.c: dmach.h
|
||||
|
||||
files.o main.o rmach.o : $(EMHOME)/h/em_path.h
|
||||
|
||||
main.o : $(EMHOME)/h/local.h
|
||||
|
||||
svars.o: ack.h
|
||||
|
||||
dmach.c intable.c: mktables dmach.h
|
||||
: mktables $(ACKDIR) # $(FE) $(INTABLES)
|
||||
mktables $(ACKDIR)
|
||||
|
||||
mktables: mktables.c
|
||||
$(CC) -o mktables mktables.c
|
||||
|
||||
pr:
|
||||
@pr Makefile $(HFILES) $(DSRC)
|
||||
|
||||
opr:
|
||||
make pr | opr
|
||||
|
||||
lint: $(ISRC)
|
||||
lint -hbx $(INCLUDES) $(DSRC) $(ISRC)
|
||||
442
util/ack/ack.1.X
442
util/ack/ack.1.X
@@ -1,442 +0,0 @@
|
||||
.\" $Id$
|
||||
.de SB
|
||||
.\" SuBheader
|
||||
.sp 1
|
||||
.PP
|
||||
.nr Sf \\n(.f
|
||||
.ft B
|
||||
\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
|
||||
.ft \\n(Sf
|
||||
.sp 1
|
||||
..
|
||||
.TH ACK 1 "$Revision$"
|
||||
.ad
|
||||
.SH NAME
|
||||
ack \- Amsterdam Compiler Kit
|
||||
.SH SYNOPSIS
|
||||
\fBack\fP arguments
|
||||
.br
|
||||
\fBacc\fP arguments
|
||||
.br
|
||||
\fBapc\fP arguments
|
||||
.br
|
||||
\fBabc\fP arguments
|
||||
.br
|
||||
\fBm2\fP arguments
|
||||
.br
|
||||
\fBocm\fP arguments
|
||||
.br
|
||||
\fBf2c\fP arguments
|
||||
.br
|
||||
\fImachine\fP arguments
|
||||
.SH DESCRIPTION
|
||||
This program transforms sources in several
|
||||
languages to load files for a variety of machines,
|
||||
internally using several phases.
|
||||
The transformation can be stopped at any phase.
|
||||
Combining sources from several languages is allowed.
|
||||
The run-time system of the first language mentioned,
|
||||
either in the program call name or in the arguments,
|
||||
is automatically included.
|
||||
The libraries of all other languages mentioned,
|
||||
containing most of the run-time systems,
|
||||
are also automatically included.
|
||||
Two types of load files can be distinguished,
|
||||
\fIa.out\fP files containing machine code and \fIe.out\fP
|
||||
files containing virtual EM machine code.
|
||||
The last type is designed for interpretation; it is obtained by calling
|
||||
the compiler as \fIem22\fP, \fIem24\fP, or \fIem44\fP.
|
||||
Compilation time for interpretation is fast and gives many
|
||||
runtime checks,
|
||||
but execution with \fIem\fP(1) is about seven times slower.
|
||||
Execution with \fIint\fP(1) is even slower than that, but available on
|
||||
more machines.
|
||||
Which combinations of languages and machines are allowed varies
|
||||
in time and depends on the installation.
|
||||
.PP
|
||||
The actions of \fIack\fP are to repeatedly transform files with a
|
||||
particular suffix into files with another suffix,
|
||||
finally combining the results into a single file.
|
||||
.PP
|
||||
Different machines can use different suffices,
|
||||
but the following are recognized by most machines:
|
||||
.IP .p
|
||||
Pascal program.
|
||||
.IP .c
|
||||
C module.
|
||||
.IP .b
|
||||
Basic program.
|
||||
.IP .ocm
|
||||
Occam program.
|
||||
.IP .mod
|
||||
Modula-2 module.
|
||||
.IP .f
|
||||
Fortran module.
|
||||
.IP .e
|
||||
EM assembly module in human readable form.
|
||||
.IP .k
|
||||
Compact EM assembly code.
|
||||
.IP .m
|
||||
Optimized compact EM assembly code.
|
||||
.IP .s
|
||||
Machine assembly language code.
|
||||
.IP .o
|
||||
Object file.
|
||||
.PP
|
||||
\fIAck\fP accepts the following flags:
|
||||
.SB machine used
|
||||
.IP \-m\fImachine\fP
|
||||
This flag tells \fIack\fP to generate a load file for \fImachine\fP.
|
||||
\fIMachine\fP can also be used as the program call
|
||||
name, instead of \fIack\fP.
|
||||
e.g. \fIack \-mi86 file.p\fP is equivalent to \fIi86
|
||||
file.p\fP.
|
||||
.SB output files
|
||||
.IP \-o
|
||||
Use the next argument as the name of the resulting file.
|
||||
\fIAck\fP produces \fIa.out\fP or \fIe.out\fP by default.
|
||||
This flag can always be used when \fIack\fP produces a single output file,
|
||||
as in
|
||||
.br
|
||||
.ti +5
|
||||
\fBack -c.s main.c -o new.s\fP.
|
||||
.br
|
||||
The output is produced on \fInew.s\fP instead of \fImain.s\fP.
|
||||
.IP \-c\fI.suffix\fP
|
||||
.IP \-c
|
||||
\fIAck\fP tries to transform each source into a file with the \fIsuffix\fP.
|
||||
When no \fIsuffix\fP is specified \fIack\fP stops just
|
||||
before the phase where it combines all arguments into a load file,
|
||||
thereby transforming the sources into \fI.k\fP, \fI.s\fP,
|
||||
\&\fI.o\fP or \fI.m\fP files.
|
||||
One extra \fIsuffix\fP is recognized here, \fI.i\fP,
|
||||
this tells \fIack\fP to only preprocess all human readable sources,
|
||||
producing files with \fIsuffix\fP \fI.i\fP.
|
||||
.br
|
||||
Note: \fIack\fP refuses to overwrite argument \fI.e\fP files.
|
||||
.IP \-t
|
||||
Preserve all intermediate files.
|
||||
If two \fB\-t\fP are used,
|
||||
\fIack\fP also preserves core dumps and output of failed transformations.
|
||||
.SB messages
|
||||
.IP \-w
|
||||
Suppress all warning messages.
|
||||
.IP \-v
|
||||
Verbose.
|
||||
Print information while juggling with files.
|
||||
.IP \-KR
|
||||
Tell the C-compiler to conform to "Kernighan & Ritchie" C.
|
||||
.IP \-ansi
|
||||
Tell \fIack\fP to use the ANSI C compiler instead of the old one.
|
||||
.IP \-fp
|
||||
Use the software floating point package, if present.
|
||||
.SB preprocessing
|
||||
.IP \-I\fIdir\fP
|
||||
\&\`#include\' files whose names do not begin with \`/\' are
|
||||
always sought first in the directory of the \fIfile\fP argument,
|
||||
then in the directories named in \fB\-I\fP options,
|
||||
then in directories on a standard list.
|
||||
.IP \-D\fIname=def\fP
|
||||
.IP \-D\fIname\fP
|
||||
Define the \fIname\fP to the preprocessor,
|
||||
as if by \`#define\'.
|
||||
If no definition is given the \fIname\fP is defined as 1.
|
||||
.IP \-U\fIname\fP
|
||||
Remove any initial definition of \fIname\fP, before
|
||||
preprocessing.
|
||||
.IP \-P
|
||||
Don't generate line directives.
|
||||
.IP \-C
|
||||
Leave C-comments in.
|
||||
.SB debugging
|
||||
.IP \-p
|
||||
This flag tells both the Pascal and C front ends to include
|
||||
code enabling the user to do some monitoring/debugging.
|
||||
Each time a routine is entered the routine \fBprocentry\fP
|
||||
is called and just before each return \fBprocexit\fP is called.
|
||||
These routines are supplied with one parameter, a pointer
|
||||
to a string containing the name of the routine.
|
||||
.SB optimizing
|
||||
.IP \-O
|
||||
.IP \-O\fInum\fP
|
||||
.IP \-O\fIopt1,opt2,...\fP
|
||||
Try to use the named optimizers, or, if no optimizers are given,
|
||||
try to use the optimizers with optimization level <= \fInum\fP (default 1).
|
||||
For optimizer names, see the table at the end of this manual page.
|
||||
Currently, only the global optimizer has a level > 1.
|
||||
Higher levels will invoke more passes of the global optimizer.
|
||||
For the global optimizer, it is also possible to indicate explicitly which
|
||||
phases must be executed, using the following flags:
|
||||
.RS
|
||||
.IP \-EGO-IL
|
||||
Inline substitution.
|
||||
.IP \-EGO-CS
|
||||
Common subexpression elimination.
|
||||
.IP \-EGO-SR
|
||||
Strength reduction.
|
||||
.IP \-EGO-UD
|
||||
Use definition analysis.
|
||||
.IP \-EGO-LV
|
||||
Live variable analysis.
|
||||
.IP \-EGO-RA
|
||||
Register allocation.
|
||||
.IP \-EGO-SP
|
||||
Stack pollution.
|
||||
.IP \-EGO-BO
|
||||
Branch optimization.
|
||||
.IP \-EGO-CJ
|
||||
Cross jumping.
|
||||
.RE
|
||||
.IP ""
|
||||
Also, the following flags may be used:
|
||||
.RS
|
||||
.IP \-s<num>
|
||||
Give an indication to the inline substitution phase,
|
||||
how much bigger the program may get,
|
||||
in percentage. This is only used as a rough indication.
|
||||
The inline substitution phase will not make the program bigger when given \-s0.
|
||||
.IP \-a
|
||||
Indicate to the inline substitution phase that it is offered the whole program.
|
||||
This allows it to throw away routines that it has substituted inline.
|
||||
.IP \-Q
|
||||
Give some statistics.
|
||||
.IP \-T
|
||||
Optimize for time.
|
||||
.IP \-S
|
||||
Optimize for size.
|
||||
.RE
|
||||
.IP ""
|
||||
In principle, the optimization phases can be run in any order; a phase
|
||||
may even be run more than once. However, the following rules must be obeyed:
|
||||
.RS
|
||||
.IP -
|
||||
the Live Variable analysis phase (LV) must be run prior to the
|
||||
Register Allocation phase (SA), as SA uses information produced by LV.
|
||||
.IP -
|
||||
SA should be the last phase.
|
||||
.RE
|
||||
.IP ""
|
||||
Also, the following may be of use:
|
||||
.RS
|
||||
.IP -
|
||||
Inline Substitution (IL) may create new opportunities for most other phases,
|
||||
so it should be run as early as possible.
|
||||
.IP -
|
||||
Use Definition analysis (UD) may introduce opportunities for LV.
|
||||
.IP -
|
||||
Strength Reduction (SR) may create opportunities for UD.
|
||||
.RE
|
||||
.IP ""
|
||||
The global optimizer is a combiner, so it should be offered all the source
|
||||
files of the program. This is not strictly necessary, but it makes the
|
||||
global optimizer more effective.
|
||||
The current default optimization phases are:
|
||||
.RS
|
||||
.IP -
|
||||
for \-O2: CJ, BO, SP;
|
||||
.IP -
|
||||
for \-O3: CS, SR, CJ, BO, SP, UD, LV, RA;
|
||||
.IP -
|
||||
for \-O4: IL, CS, SR, CJ, BO, SP, UD, LV, RA;
|
||||
.IP -
|
||||
for higher levels: as for \-O4.
|
||||
.RE
|
||||
.IP \-L
|
||||
Disable the generation of code by the front ends to
|
||||
record line number and source file name at run-time.
|
||||
(This is the default for C and Fortran).
|
||||
.SB libraries
|
||||
.IP \-l\fIname\fP
|
||||
Tells \fIack\fP to insert a library module at this point.
|
||||
For example: the library \fImon\fP contains the
|
||||
routines for systems calls needed by both C and Pascal.
|
||||
.IP \-.\fIsuffix\fP
|
||||
When linking multiple \fI.o\fP or \fI.m\fP files created by
|
||||
separate calls of \fIack\fP together, \fIack\fP cannot deduce
|
||||
the run-time system needed,
|
||||
unless called as \fIapc\fP, \fIabc\fP, \fIocm\fP, \fIm2\fP, \fIf2c\fP, or \fIacc\fP.
|
||||
This flag serves to tell \fIack\fP which runtime system is
|
||||
needed in such a case.
|
||||
For example: "ack \-c x.c ; ack \-.c x.o".
|
||||
.IP \-r.\fIsuffix\fP
|
||||
Most frontends and backends use one or
|
||||
more run-time libraries.
|
||||
These flags tell \fIack\fP to include the libraries needed when
|
||||
a file with \fIsuffix\fP would be included in the arguments.
|
||||
.IP \-LIB
|
||||
This flag tells the peephole optimizer
|
||||
.RF em_opt 6
|
||||
to add information about the visibility of the names used
|
||||
to each output module.
|
||||
This is needed by
|
||||
assembler/linkers when these modules are to be inserted
|
||||
in libraries.
|
||||
.SB interpreter
|
||||
.IP \-{xxx}
|
||||
The string starting after \`{\' and terminated by a \`}\' is passed
|
||||
as an option string to the Pascal compiler and supersedes corresponding
|
||||
options given in the source file.
|
||||
See the ACK reference manual [4] for a list of options.
|
||||
.IP "\-+xxx, \-\-xxx"
|
||||
When interpreting programs, these flags are used to select some
|
||||
options during interpretation, like test, profile, flow, extra and count.
|
||||
A short description of these flags follows:
|
||||
.RS
|
||||
.IP " t(est)" 12
|
||||
test for undefined, overflow, array bound etc.
|
||||
.IP " f(low)"
|
||||
keep track of executed source lines.
|
||||
.IP " c(ount)"
|
||||
count the number of times a source line is executed.
|
||||
.IP " p(rofile)"
|
||||
count the memory cycles executed per source line.
|
||||
.RE
|
||||
.IP "" 5
|
||||
Test is on by default, the others are off. Normally, these
|
||||
flag options are given each time the interpreter is run.
|
||||
The EM assembler/linker offers the opportunity to change
|
||||
the defaults per program.
|
||||
The changed options are recorded in the "e.out" header.
|
||||
These flags \-\- and \-+ are passed to the assembler for this purpose.
|
||||
So, \-\-t and \-+pfce invert the defaults.
|
||||
.SB general
|
||||
.IP \-R\fIprogram=xxx\fP
|
||||
Replace the \fIprogram\fP by the pathname \fIxxx\fP.
|
||||
The program names referred to later in this manual are allowed here.
|
||||
.IP \-R\fIprogram\-xxx\fP
|
||||
The flag argument \fI\-xxx\fP is given to \fIprogram\fP.
|
||||
.IP \-R\fIprogram:n\fP
|
||||
Set the priority of the indicated transformation to \fIn\fP.
|
||||
The default priority is 0, setting it to -1 makes it highly
|
||||
unlikely the the phase will be used, setting it to 1 makes
|
||||
it very likely that the phase will be used.
|
||||
.IP \-k
|
||||
Do not stop when an error occurs, but try to transform all
|
||||
other arguments as far as possible.
|
||||
.IP \-g
|
||||
Instruct the front-end and back-end to produce symbolic debugger information
|
||||
for \fIgrind\fP(1). This is currently supported by the following front-ends:
|
||||
C, ANSI-C, Pascal, Modula-2, and the following back-ends: Motorola M68020,
|
||||
Sparc, Vax, Intel 80386.
|
||||
.IP \-gdb
|
||||
Instruct the front-end and back-end to produce symbolic debugger information
|
||||
for \fIgdb\fP. This is currently supported by the following front-ends:
|
||||
C, ANSI-C, Pascal, Modula-2, and the following back-ends: Motorola M68020,
|
||||
Sparc, Vax, Intel 80386.
|
||||
.PP
|
||||
All arguments without a suffix or with an unrecognized suffix
|
||||
are passed to the loaders, as for flags.
|
||||
.SH PREPROCESSOR
|
||||
All C source programs are run through the preprocessor
|
||||
before they are fed to the compiler proper.
|
||||
On larger machines, the compiler has a built in preprocessor.
|
||||
Other human readable sources (Modula-2, Pascal, or Basic programs and
|
||||
machine assembly) are only preprocessed when they start with a \`#\'.
|
||||
.PP
|
||||
\fIAck\fP adds a few macro definitions when it calls the
|
||||
preprocessor.
|
||||
These macro\'s contain the word- and pointer-size and the sizes
|
||||
of some basic types used by the Pascal, Basic and/or C compiler.
|
||||
All sizes are in bytes.
|
||||
.sp 1
|
||||
.TS
|
||||
tab(:);
|
||||
l l l l.
|
||||
EM_WSIZE:wordsize:EM_PSIZE:pointer size
|
||||
EM_SSIZE:size of shorts (C):EM_LSIZE:size of longs (C+Pascal)
|
||||
EM_FSIZE:size of floats (C):EM_DSIZE:size of doubles (C+Pascal)
|
||||
.TE
|
||||
.sp 1
|
||||
The name of the \fImachine\fP or something like it when
|
||||
the machine name is numeric is also defined (as 1).
|
||||
As the ANSI C rules forbid this, in ANSI C, underscores are prepended to
|
||||
these names.
|
||||
.PP
|
||||
The default directories searched for include files differ for each machine.
|
||||
.SH PROGRAMS
|
||||
\fIAck\fP uses one or more programs in each phase of the
|
||||
transformation.
|
||||
The table below gives the names \fIack\fP uses for these
|
||||
programs.
|
||||
Internally \fIack\fP maintains a mapping of these names to pathnames
|
||||
for load files.
|
||||
The table specifies which type of files are accepted by each
|
||||
program as input and the file type produced as output.
|
||||
.sp 1
|
||||
.in +2
|
||||
.TS
|
||||
tab(:);
|
||||
l l l l.
|
||||
input:name:output:description
|
||||
\&.f:f77:.c:Fortran-to-C front end
|
||||
\&.c:cem:.k:C front end [4,5,6]
|
||||
\&.p:pc:.k:Pascal front end [2,3,6]
|
||||
\&.b:abc:.k:Basic front end [6,8]
|
||||
\&.ocm:ocm:.k:Occam front end [9]
|
||||
\&.mod:m2:.k:Modula-2 front end [11]
|
||||
\&.e:encode:.k:Compactify EM assembly language [1]
|
||||
\&.k:opt:.m:EM peephole optimizer
|
||||
\&.k .m:decode:.e:Produce human readable EM assembly
|
||||
\&.k .m:emass:e.out:Linker producing EM machine code [1]
|
||||
\&.m:ego:.gk:EM global optimizer [10]
|
||||
\&.gk:opt2:.g:Second EM peephole optimizer
|
||||
\&.m .g:be:.s:backend
|
||||
\&.s:asopt:.so:target optimizer
|
||||
\&.s .so:asld:.out:Assembler/linker, Ack object format
|
||||
\&.s .so:as:.o:Assembler, relocatable object
|
||||
\&.o:ld:a.out:Linker, machine a.out format
|
||||
\&.o:led:.out:Linker, Ack object format
|
||||
\&.o:cv:a.out:Conversion from Ack object to machine object
|
||||
.TE
|
||||
.in -2
|
||||
.SH "ENVIRONMENT VARIABLES"
|
||||
.IP ACKDIR
|
||||
If set, this environment variable overrides ack's idea of its home
|
||||
directory.
|
||||
.IP ACKM
|
||||
If set, this environment variable overrides ack's idea of the default
|
||||
machine it compiles for.
|
||||
.IP ACKFE
|
||||
If set, this environment variable tells ack where to get the front-end
|
||||
description file.
|
||||
.SH "SEE ALSO"
|
||||
.PD 0
|
||||
em_opt(6), em_ass(6), em_cg(6), ack.out(5)
|
||||
.IP [1]
|
||||
A.S. Tanenbaum, Hans van Staveren, Ed Keizer and Johan
|
||||
Stevenson, \fIDescription of a machine architecture for use with
|
||||
block structured languages\fP, Informatica rapport IR-81.
|
||||
.IP [2]
|
||||
K. Jensen and N. Wirth,
|
||||
\fIPASCAL, User manual and report\fP Springer Verlag.
|
||||
.IP [3]
|
||||
The ISO Pascal standard proposal ISO/TC97/SC5-N462.
|
||||
.IP [4]
|
||||
B.W. Kernighan and D.M. Ritchie, \fIThe C Programming
|
||||
language\fP, Prentice-Hall, 1978
|
||||
.IP [5]
|
||||
D.M. Ritchie, \fI C Reference Manual\fP
|
||||
.IP [6]
|
||||
Amsterdam Compiler Kit, reference manuals and UNIX manual pages.
|
||||
.IP [7]
|
||||
E.G. Keizer, Ack description file reference manual.
|
||||
.IP [8]
|
||||
M.L. Kersten a.o., \fIThe ABC compiler\fP.
|
||||
.IP [9]
|
||||
Kees Bot and Edwin Scheffer, \fIAn Occam Compiler\fP, IM-6.
|
||||
.IP [10]
|
||||
H.E. Bal, \fIThe design and implementation of the EM Global Optimizer\fP,
|
||||
Informatica rapport IR-99.
|
||||
.IP [11]
|
||||
C.J.H. Jacobs, \fIThe ACK Modula-2 Compiler\fP.
|
||||
.PD
|
||||
.SH DIAGNOSTICS
|
||||
.PD
|
||||
The diagnostics are intended to be self\-explanatory.
|
||||
.SH BUGS
|
||||
Not all warning messages are superseded by \fB\-w\fP.
|
||||
.br
|
||||
Argument assembly files are not preprocessed when fed into the
|
||||
universal assembler/loader.
|
||||
.SH AUTHOR
|
||||
Ed Keizer, Vrije Universiteit, Amsterdam
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#ifndef NORCSID
|
||||
#define RCS_ACK "$Id$"
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/* User settable options */
|
||||
/****************************************************************************/
|
||||
|
||||
#define FRONTENDS "fe" /* The front-end definitions */
|
||||
#define TMPNAME "Ack_%x" /* Naming of temp. files */
|
||||
|
||||
/****************************************************************************/
|
||||
/* Internal mnemonics, should not be tinkered with */
|
||||
/****************************************************************************/
|
||||
|
||||
/* The names of some string variables */
|
||||
|
||||
#define HOME "EM"
|
||||
#define RTS "RTS"
|
||||
#define HEAD "HEAD"
|
||||
#define TAIL "TAIL"
|
||||
#define SRC "SOURCE"
|
||||
#define LIBVAR "LNAME"
|
||||
#define SUFFIX "SUFFIX"
|
||||
|
||||
/* Intended for flags, possibly in bit fields */
|
||||
|
||||
#define YES 1
|
||||
#define NO 0
|
||||
#define MAYBE 2
|
||||
|
||||
#define EXTERN extern
|
||||
|
||||
#define SUFCHAR '.' /* Start of SUFFIX in file name */
|
||||
#define SPACE ' '
|
||||
#define TAB '\t'
|
||||
#define EQUAL '='
|
||||
#define S_VAR '{' /* Start of variable */
|
||||
#define C_VAR '}' /* End of variable */
|
||||
#define A_VAR '?' /* Variable alternative */
|
||||
#define BSLASH '\\' /* Backslash */
|
||||
#define STAR '*' /* STAR */
|
||||
#define C_IN '<' /* Token specifying input */
|
||||
#define C_OUT '>' /* Token specifying output */
|
||||
#define S_EXPR '(' /* Start of expression */
|
||||
#define C_EXPR ')' /* End of expression */
|
||||
#define M_EXPR ':' /* Middle of two suffix lists */
|
||||
#define T_EXPR '=' /* Start of tail */
|
||||
|
||||
#define NO_SCAN 0200 /* Bit set in character to defeat recogn. */
|
||||
|
||||
typedef struct {
|
||||
char *p_path; /* points to the full pathname */
|
||||
int p_keeps:1; /* The string should be thrown when unused */
|
||||
int p_keep:1; /* The file should be thrown away after use */
|
||||
} path ;
|
||||
|
||||
#define p_cont(elem) ((path *)l_content(elem))
|
||||
|
||||
/* Return values of setpath() */
|
||||
enum f_path { F_OK, F_NOMATCH, F_NOPATH } ;
|
||||
|
||||
/* Library routines */
|
||||
|
||||
extern char *strindex();
|
||||
extern char *strrindex();
|
||||
extern char *strcpy();
|
||||
extern char *strcat();
|
||||
extern int getpid();
|
||||
extern int unlink();
|
||||
extern int close();
|
||||
extern int open();
|
||||
extern int creat();
|
||||
|
||||
/* Own routines */
|
||||
enum f_path getpath();
|
||||
enum f_path scan_end();
|
||||
extern void noodstop();
|
||||
extern char *getvar();
|
||||
extern char *keeps();
|
||||
extern char *basename();
|
||||
extern char *skipblank();
|
||||
extern char *firstblank();
|
||||
extern char *getcore();
|
||||
extern char *changecore();
|
||||
#define freecore(area) free(area)
|
||||
|
||||
#define DEBUG 1 /* Allow debugging of Ack */
|
||||
|
||||
#ifndef DEBUG
|
||||
# define debug 0 /* To surprise all these 'if ( debug ) 's */
|
||||
#else
|
||||
extern int debug ;
|
||||
#endif
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "ack.h"
|
||||
#include "list.h"
|
||||
#include "trans.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#define EXTERN
|
||||
|
||||
#include "data.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_data[] = RCS_DATA ;
|
||||
#endif
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#ifndef NORCSID
|
||||
#define RCS_DATA "$Id$"
|
||||
#endif
|
||||
|
||||
EXTERN char *stopsuffix; /* Suffix to stop at */
|
||||
EXTERN char *machine; /* The machine id */
|
||||
EXTERN char *callname; /* argv[0] */
|
||||
EXTERN char *rts; /* The runtime-system */
|
||||
EXTERN char *rtsuf; /* The runtime-system module suffix */
|
||||
EXTERN char *Optlist; /* Which optimizers */
|
||||
|
||||
EXTERN list_head arguments; /* List of arguments */
|
||||
EXTERN list_head flags; /* List of flags */
|
||||
|
||||
EXTERN list_head tr_list; /* List of transformations */
|
||||
|
||||
EXTERN list_head R_list; /* List of -R flags */
|
||||
EXTERN list_head head_list; /* List of suffices for headers */
|
||||
EXTERN list_head tail_list; /* List of suffices for tails */
|
||||
|
||||
EXTERN int k_flag; /* Like -k of lint */
|
||||
EXTERN int t_flag; /* Preserve intermediate files */
|
||||
EXTERN int v_flag; /* Verbose */
|
||||
EXTERN int w_flag; /* Don't print warnings */
|
||||
EXTERN int nill_flag; /* Don't print file names */
|
||||
EXTERN int Optlevel; /* Optimizing */
|
||||
|
||||
#ifdef DEBUG
|
||||
EXTERN int debug; /* Debugging control */
|
||||
#endif
|
||||
|
||||
EXTERN int n_error; /* Number of errors encountered */
|
||||
|
||||
EXTERN char *progname; /* The program call name */
|
||||
|
||||
EXTERN char *outfile; /* The result file e.g. a.out */
|
||||
EXTERN char template[20]; /* The template for temporary file
|
||||
names */
|
||||
|
||||
EXTERN trf *linker; /* Pointer to the Loader/Linker */
|
||||
EXTERN trf *cpp_trafo; /* Pointer to C-preprocessor */
|
||||
|
||||
EXTERN path in; /* The current single input pathname */
|
||||
EXTERN path out; /* The current output pathname */
|
||||
EXTERN path orig; /* The original input path */
|
||||
EXTERN char *p_basename; /* The current basename */
|
||||
EXTERN char *p_suffix; /* The current input suffix */
|
||||
@@ -1,23 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/***************************************************************/
|
||||
/* */
|
||||
/* Definition for table that maps a name on an intable index */
|
||||
/* */
|
||||
/***************************************************************/
|
||||
|
||||
#ifndef NORCSID
|
||||
#define RCS_DMACH "$Id$"
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
char *ma_name ; /* The name of the machine */
|
||||
int ma_index ;
|
||||
} dmach ;
|
||||
|
||||
extern dmach massoc[] ;
|
||||
|
||||
extern char intable[] ;
|
||||
180
util/ack/files.c
180
util/ack/files.c
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ack.h"
|
||||
#include "list.h"
|
||||
#include "trans.h"
|
||||
#include "grows.h"
|
||||
#include "data.h"
|
||||
#include <em_path.h>
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
char *add_u(part,ptr) char *ptr ; {
|
||||
if ( part>=26 ) {
|
||||
ptr=add_u(part/26-1,ptr) ;
|
||||
}
|
||||
*ptr= part%26 + 'a' ;
|
||||
return ptr+1 ;
|
||||
}
|
||||
|
||||
char *unique() {
|
||||
/* Get the next unique part of the internal filename */
|
||||
static int u_next = 0 ;
|
||||
static char buf[10] ;
|
||||
register char *ptr ;
|
||||
|
||||
ptr=add_u(u_next,buf) ;
|
||||
*ptr=0 ;
|
||||
u_next++ ;
|
||||
return buf ;
|
||||
}
|
||||
|
||||
setfiles(phase) register trf *phase ; {
|
||||
/* Set the out structure according to the in structure,
|
||||
the transformation and some global data */
|
||||
growstring pathname ;
|
||||
register list_elem *elem ;
|
||||
static int out_used= 0 ;
|
||||
|
||||
if ( !phase->t_next && !phase->t_isprep && outfile ) {
|
||||
if ( out_used ) {
|
||||
fuerror("only one output file allowed when using the -o flag") ;
|
||||
} else {
|
||||
if ( !phase->t_keep ) fatal("Removing result file") ;
|
||||
phase->t_outfile=outfile ;
|
||||
out_used++ ;
|
||||
}
|
||||
}
|
||||
if ( phase->t_combine ) {
|
||||
in.p_path= (char *)0 ;
|
||||
in.p_keep=YES ;
|
||||
in.p_keeps=NO ;
|
||||
}
|
||||
if ( phase->t_outfile && phase->t_keep ) {
|
||||
out.p_path=phase->t_outfile ;
|
||||
out.p_keeps=NO ;
|
||||
out.p_keep=YES ;
|
||||
} else {
|
||||
gr_init(&pathname) ;
|
||||
if ( !phase->t_keep && !t_flag ) {
|
||||
gr_cat(&pathname,TMP_DIR) ;
|
||||
gr_cat(&pathname,"/") ;
|
||||
gr_cat(&pathname,template) ;
|
||||
gr_cat(&pathname,unique()) ;
|
||||
out.p_keep=NO ;
|
||||
} else {
|
||||
if ( !p_basename ) {
|
||||
gr_cat(&pathname,"Ack") ;
|
||||
gr_cat(&pathname,unique()) ;
|
||||
p_basename=keeps(gr_start(pathname)) ;
|
||||
werror("Output written on %s%s",
|
||||
p_basename,phase->t_out) ;
|
||||
} else {
|
||||
gr_cat(&pathname,p_basename) ;
|
||||
}
|
||||
out.p_keep=YES ;
|
||||
}
|
||||
gr_cat(&pathname,phase->t_out) ;
|
||||
out.p_path= gr_final(&pathname) ;
|
||||
out.p_keeps= YES ;
|
||||
}
|
||||
scanlist( l_first(arguments), elem) {
|
||||
if ( strcmp(l_content(*elem),out.p_path)==0 ) {
|
||||
error("attempt to overwrite %s",out.p_path) ;
|
||||
return 0 ;
|
||||
}
|
||||
}
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
disc_files(phase) trf *phase ; {
|
||||
path temp ;
|
||||
|
||||
if ( !phase->t_combine ) {
|
||||
file_final(&in) ;
|
||||
} else {
|
||||
disc_inputs(phase) ;
|
||||
}
|
||||
temp=in ; in=out ; out=temp ;
|
||||
}
|
||||
|
||||
file_final(file) path *file ; {
|
||||
if ( file->p_path ) {
|
||||
if ( !file->p_keep && t_flag<=1 ) {
|
||||
if ( unlink(file->p_path)!=0 ) {
|
||||
werror("couldn't unlink %s",file->p_path);
|
||||
}
|
||||
}
|
||||
if ( file->p_keeps ) throws(file->p_path) ;
|
||||
}
|
||||
file->p_path= (char *)0 ;
|
||||
file->p_keeps=NO ;
|
||||
file->p_keep=NO ;
|
||||
}
|
||||
|
||||
disc_inputs(phase) trf *phase ; {
|
||||
/* Remove all the input files of this phase */
|
||||
/* Only for combiners */
|
||||
register path *l_in ;
|
||||
register list_elem *elem ;
|
||||
scanlist( l_first(phase->t_inputs), elem) {
|
||||
l_in= p_cont(*elem) ;
|
||||
file_final(l_in) ;
|
||||
freecore((char *)l_in) ;
|
||||
}
|
||||
l_clear(&phase->t_inputs) ;
|
||||
}
|
||||
|
||||
rmfile(file) path *file ; {
|
||||
/* Remove a file, do not complain when is does not exist */
|
||||
if ( file->p_path ) {
|
||||
if ( t_flag<=1 ) unlink(file->p_path) ;
|
||||
if ( file->p_keeps ) throws(file->p_path) ;
|
||||
file->p_path= (char *)0 ;
|
||||
file->p_keeps=NO ;
|
||||
file->p_keep=NO ;
|
||||
}
|
||||
}
|
||||
|
||||
rmtemps() {
|
||||
/* Called in case of disaster, always remove the current output file!
|
||||
*/
|
||||
register list_elem *elem ;
|
||||
|
||||
if ( t_flag>1 ) return ;
|
||||
rmfile(&out) ;
|
||||
file_final(&in) ;
|
||||
scanlist(l_first(tr_list),elem) {
|
||||
if ( t_cont(*elem)->t_combine && t_cont(*elem)->t_do ) {
|
||||
disc_inputs(t_cont(*elem)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
add_input(file,phase) path *file ; trf *phase ; {
|
||||
register path *store ;
|
||||
#ifdef DEBUG
|
||||
if ( debug ) {
|
||||
vprint("Adding %s to inputs of %s\n",
|
||||
file->p_path,phase->t_name) ;
|
||||
}
|
||||
#endif
|
||||
phase->t_do=YES ;
|
||||
if ( !phase->t_origname && orig.p_path[0]!='-' ) {
|
||||
/* This entry decides the name of the result */
|
||||
phase->t_origname= orig.p_path ;
|
||||
}
|
||||
store= (path *) getcore(sizeof (path)) ;
|
||||
*store = *file ;
|
||||
l_add(&phase->t_inputs,(char *)store) ;
|
||||
/* The task of getting rid of the string is passed to 'phase',
|
||||
as is the task to get rid of the file itself.
|
||||
*/
|
||||
file->p_keeps=NO ; file->p_keep=YES ;
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* Bookkeeping for growing strings */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "ack.h"
|
||||
#include "grows.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
static char rcs_grows[] = RCS_GROWS ;
|
||||
#endif
|
||||
|
||||
gr_add(id,c) register growstring *id ; char c ; {
|
||||
if ( id->gr_size==id->gr_max) {
|
||||
if ( id->gr_size==0 ) { /* The first time */
|
||||
id->gr_max= 2*GR_MORE ;
|
||||
id->gr_string= getcore(id->gr_max) ;
|
||||
} else {
|
||||
id->gr_max += GR_MORE ;
|
||||
id->gr_string= changecore(id->gr_string,id->gr_max ) ;
|
||||
}
|
||||
}
|
||||
*(id->gr_string+id->gr_size++)= c ;
|
||||
}
|
||||
|
||||
gr_cat(id,string) growstring *id ; char *string ; {
|
||||
register char *ptr ;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( id->gr_size && *(id->gr_string+id->gr_size-1) ) {
|
||||
vprint("Non-zero terminated %*s\n",
|
||||
id->gr_size, id->gr_string ) ;
|
||||
}
|
||||
#endif
|
||||
if ( id->gr_size ) id->gr_size-- ;
|
||||
ptr=string ;
|
||||
for (;;) {
|
||||
gr_add(id,*ptr) ;
|
||||
if ( *ptr++ ) continue ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
gr_throw(id) register growstring *id ; {
|
||||
/* Throw the string away */
|
||||
if ( id->gr_max==0 ) return ;
|
||||
freecore(id->gr_string) ;
|
||||
id->gr_string = 0 ;
|
||||
id->gr_max=0 ;
|
||||
id->gr_size=0 ;
|
||||
}
|
||||
|
||||
gr_init(id) growstring *id ; {
|
||||
id->gr_size=0 ; id->gr_max=0 ;
|
||||
}
|
||||
|
||||
char *gr_final(id) growstring *id ; {
|
||||
/* Throw away the bookkeeping, adjust the string to its final
|
||||
length and return a pointer to a string to be get rid of with
|
||||
throws
|
||||
*/
|
||||
register char *retval ;
|
||||
retval= keeps(gr_start(*id)) ;
|
||||
gr_throw(id) ;
|
||||
return retval ;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#ifndef NORCSID
|
||||
#define RCS_GROWS "$Id$"
|
||||
#endif
|
||||
|
||||
/* struct used to identify and do bookkeeping for growing strings */
|
||||
|
||||
typedef struct {
|
||||
char *gr_string ; /* Points to start of string */
|
||||
unsigned gr_size ; /* Current string size */
|
||||
unsigned gr_max ; /* Maximum string size */
|
||||
} growstring ;
|
||||
|
||||
#define GR_MORE 50 /* Steps to grow */
|
||||
|
||||
#define gr_start(id) (id).gr_string /* The start of the string */
|
||||
|
||||
/* Routines used */
|
||||
|
||||
extern int gr_throw() ; /* To free the core */
|
||||
extern int gr_add() ; /* To add one character */
|
||||
extern int gr_cat() ; /* concatenate the contents and the string */
|
||||
extern int gr_init() ; /* Initialize the bookkeeping */
|
||||
extern char *gr_final() ; /* Transform to a stable storage string */
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ack.h"
|
||||
#include "list.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
static char rcs_list[] = RCS_LIST ;
|
||||
#endif
|
||||
|
||||
/* List handling, operations allowed:
|
||||
adding strings to the list,
|
||||
throwing away whole lists,
|
||||
linearize a list.
|
||||
|
||||
Routines:
|
||||
l_add(header,string) Add an element to a list.
|
||||
header List header, list_head *
|
||||
string String pointer, char *
|
||||
the string is NOT copied
|
||||
|
||||
l_clear(header) Delete an whole list.
|
||||
header List header, list_head *
|
||||
|
||||
l_throw(header) Delete a list of strings.
|
||||
header List header, list_head *
|
||||
|
||||
*/
|
||||
|
||||
|
||||
l_add(header,string) list_head *header ; char *string ; {
|
||||
register list_elem *new;
|
||||
|
||||
/* NOSTRICT */
|
||||
new= (list_elem *)getcore(sizeof *new);
|
||||
l_content(*new)= string ;
|
||||
/* NOSTRICT */
|
||||
l_next(*new)= (list_elem *)0 ;
|
||||
if ( !header->ca_first ) {
|
||||
header->ca_first= new ;
|
||||
} else {
|
||||
header->ca_last->ca_next= new ;
|
||||
}
|
||||
header->ca_last= new ;
|
||||
}
|
||||
|
||||
l_clear(header) list_head *header ; {
|
||||
register list_elem *old, *next;
|
||||
for ( old=header->ca_first ; old ; old= next ) {
|
||||
next= old->ca_next ;
|
||||
freecore((char *)old) ;
|
||||
}
|
||||
header->ca_first= (list_elem *) 0 ;
|
||||
header->ca_last = (list_elem *) 0 ;
|
||||
}
|
||||
|
||||
l_throw(header) list_head *header ; {
|
||||
register list_elem *old, *next;
|
||||
for ( old=header->ca_first ; old ; old= next ) {
|
||||
throws(l_content(*old)) ;
|
||||
next= old->ca_next ;
|
||||
freecore((char *)old) ;
|
||||
}
|
||||
header->ca_first= (list_elem *) 0 ;
|
||||
header->ca_last = (list_elem *) 0 ;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#ifndef NORCSID
|
||||
#define RCS_LIST "$Id$"
|
||||
#endif
|
||||
|
||||
struct ca_elem {
|
||||
struct ca_elem *ca_next; /* The link */
|
||||
char *ca_cont; /* The contents */
|
||||
} ;
|
||||
|
||||
struct ca_list {
|
||||
struct ca_elem *ca_first; /* The head */
|
||||
struct ca_elem *ca_last; /* The tail */
|
||||
} ;
|
||||
|
||||
typedef struct ca_list list_head ; /* The decl. for headers */
|
||||
typedef struct ca_elem list_elem ; /* The decl. for elements */
|
||||
|
||||
/* Some operations */
|
||||
|
||||
/* Access */
|
||||
#define l_first(header) (header).ca_first
|
||||
#define l_next(elem) (elem).ca_next
|
||||
#define l_content(elem) (elem).ca_cont
|
||||
|
||||
/* To be used for scanning lists, ptr is the running variable */
|
||||
#define scanlist(elem,ptr) \
|
||||
for ( ptr= elem ; ptr; ptr= l_next(*ptr) )
|
||||
452
util/ack/main.c
452
util/ack/main.c
@@ -1,452 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ack.h"
|
||||
#include "list.h"
|
||||
#include "trans.h"
|
||||
#include <local.h>
|
||||
#include "data.h"
|
||||
#include <signal.h>
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
static char rcs_ack[] = RCS_ACK ;
|
||||
#endif
|
||||
|
||||
static int sigs[] = { SIGINT, SIGHUP, SIGTERM, 0 } ;
|
||||
static int arg_count;
|
||||
|
||||
extern char *getenv();
|
||||
|
||||
main(argc,argv) char **argv ; {
|
||||
register list_elem *elem ;
|
||||
register char *frontend ;
|
||||
register int *n_sig ;
|
||||
register trf *phase ;
|
||||
|
||||
progname=argv[0];
|
||||
varinit();
|
||||
vieuwargs(argc,argv);
|
||||
if ( (frontend=getenv("ACKFE")) ) {
|
||||
setlist(frontend) ;
|
||||
} else {
|
||||
setlist(FRONTENDS);
|
||||
}
|
||||
if ( callname ) {
|
||||
if ( machine ) {
|
||||
fuerror("can not produce code for both %s and %s",
|
||||
callname,machine) ;
|
||||
}
|
||||
machine= callname ;
|
||||
}
|
||||
if ( !machine && ! (machine=getenv("ACKM")) ) {
|
||||
#ifdef ACKM
|
||||
machine= ACKM; /* The default machine */
|
||||
#else
|
||||
fuerror("No machine specified") ;
|
||||
#endif
|
||||
}
|
||||
setlist(machine);
|
||||
/* Find the linker, needed for argument building */
|
||||
scanlist(l_first(tr_list),elem) {
|
||||
if ( t_cont(*elem)->t_linker ) {
|
||||
linker= t_cont(*elem) ;
|
||||
}
|
||||
}
|
||||
transini();
|
||||
scanneeds();
|
||||
sprintf(template,TMPNAME,getpid()) ;
|
||||
if ( n_error && !k_flag ) exit(n_error) ;
|
||||
|
||||
for ( n_sig=sigs ; *n_sig ; n_sig++ ) {
|
||||
if ( signal(*n_sig,noodstop)==SIG_IGN ) {
|
||||
signal(*n_sig,SIG_IGN) ;
|
||||
}
|
||||
}
|
||||
|
||||
scanlist ( l_first(arguments), elem ) {
|
||||
arg_count++;
|
||||
}
|
||||
|
||||
scanlist ( l_first(arguments), elem ) {
|
||||
if ( !process(l_content(*elem)) && !k_flag ) exit(1) ;
|
||||
}
|
||||
orig.p_path= (char *)0 ;
|
||||
if ( !rts ) rts="." ;
|
||||
setsvar(keeps(RTS),rts) ;
|
||||
if ( linker ) getmapflags(linker) ;
|
||||
|
||||
scanlist(l_first(tr_list),elem) {
|
||||
phase=t_cont(*elem) ;
|
||||
if ( phase->t_combine && phase->t_do ) {
|
||||
if ( phase->t_blocked ) {
|
||||
#ifdef DEBUG
|
||||
if ( debug ) {
|
||||
vprint("phase %s is blocked\n",
|
||||
phase->t_name) ;
|
||||
}
|
||||
#endif
|
||||
disc_inputs(phase) ;
|
||||
continue ;
|
||||
}
|
||||
orig.p_keep=YES ;
|
||||
orig.p_keeps=NO ;
|
||||
orig.p_path=phase->t_origname ;
|
||||
if ( p_basename ) throws(p_basename) ;
|
||||
if ( orig.p_path ) {
|
||||
p_basename= keeps(basename(orig.p_path)) ;
|
||||
} else {
|
||||
p_basename=0 ;
|
||||
}
|
||||
if ( !startrf(phase) && !k_flag ) exit(1) ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( n_error ) exit(n_error) ;
|
||||
|
||||
exit(0) ;
|
||||
}
|
||||
|
||||
char *srcvar() {
|
||||
return orig.p_path ;
|
||||
}
|
||||
|
||||
char *getsuffix() {
|
||||
return strrindex(orig.p_path, SUFCHAR) ;
|
||||
}
|
||||
|
||||
varinit() {
|
||||
/* initialize the string variables */
|
||||
register char *envstr ;
|
||||
extern char *em_dir;
|
||||
|
||||
if ( envstr=getenv("ACKDIR") ) {
|
||||
em_dir = keeps(envstr);
|
||||
}
|
||||
setsvar(keeps(HOME),em_dir) ;
|
||||
setpvar(keeps(SRC),srcvar) ;
|
||||
setpvar(keeps(SUFFIX),getsuffix) ;
|
||||
}
|
||||
|
||||
/************************* flag processing ***********************/
|
||||
|
||||
vieuwargs(argc,argv) char **argv ; {
|
||||
register char *argp;
|
||||
register int nextarg ;
|
||||
register int eaten ;
|
||||
int hide ;
|
||||
|
||||
firstarg(argv[0]) ;
|
||||
|
||||
nextarg= 1 ;
|
||||
|
||||
while ( nextarg<argc ) {
|
||||
argp= argv[nextarg] ;
|
||||
nextarg++ ;
|
||||
if ( argp[0]!='-' || argp[1]=='l' ) {
|
||||
/* Not a flag, or a library */
|
||||
l_add(&arguments,argp) ;
|
||||
continue ;
|
||||
}
|
||||
|
||||
/* Flags */
|
||||
hide=NO ; /* Do not hide this flags to the phases */
|
||||
eaten=0 ; /* Did not 'eat' tail of flag yet */
|
||||
switch ( argp[1] ) {
|
||||
case 'm': if ( machine ) fuerror("Two machines?") ;
|
||||
machine= &argp[2];
|
||||
if (*machine == '\0') {
|
||||
fuerror("-m needs machine name");
|
||||
}
|
||||
eaten=1 ;
|
||||
break ;
|
||||
case 'o': if ( nextarg>=argc ) {
|
||||
fuerror("-o can't be the last flag") ;
|
||||
}
|
||||
if ( outfile ) fuerror("Two results?") ;
|
||||
outfile= argv[nextarg++] ;
|
||||
hide=YES ;
|
||||
break ;
|
||||
case 'O': Optlevel = atoi(&argp[2]);
|
||||
if (! Optlevel) Optlevel = 1;
|
||||
Optlist= &argp[2] ;
|
||||
eaten=1 ;
|
||||
break ;
|
||||
case 'v': if ( argp[2] ) {
|
||||
v_flag += atoi(&argp[2]) ;
|
||||
eaten=1 ;
|
||||
} else {
|
||||
v_flag++ ;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if ( v_flag>=3 ) debug=v_flag-2 ;
|
||||
#endif
|
||||
break ;
|
||||
case 'c': if ( stopsuffix ) fuerror("Two -c flags") ;
|
||||
stopsuffix= &argp[2]; eaten=1;
|
||||
if ( *stopsuffix && *stopsuffix!=SUFCHAR ) {
|
||||
fuerror("-c flag has invalid tail") ;
|
||||
}
|
||||
break ;
|
||||
case 'k': k_flag++ ;
|
||||
break ;
|
||||
case 't': t_flag++ ;
|
||||
break ;
|
||||
case 'R': eaten=1;
|
||||
break ;
|
||||
case 'r': if ( argp[2]!=SUFCHAR ) {
|
||||
error("-r must be followed by %c",SUFCHAR) ;
|
||||
}
|
||||
keeptail(&argp[2]); eaten=1 ;
|
||||
break ;
|
||||
case '.': if ( rts ) {
|
||||
if ( strcmp(rts,&argp[1])!=0 )
|
||||
fuerror("Two run-time systems?") ;
|
||||
} else {
|
||||
rts= &argp[1] ;
|
||||
keephead(rts) ; keeptail(rts) ;
|
||||
}
|
||||
eaten=1 ;
|
||||
break ;
|
||||
case 0 : nill_flag++ ; eaten++ ;
|
||||
hide=YES ;
|
||||
break;
|
||||
case 'w': w_flag++;
|
||||
break ;
|
||||
default: /* The flag is not recognized,
|
||||
put it on the list for the sub-processes
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
if ( debug ) {
|
||||
vprint("Flag %s: phase dependent\n",argp) ;
|
||||
}
|
||||
#endif
|
||||
l_add(&flags,keeps(argp)) ;
|
||||
eaten=1 ;
|
||||
hide=YES ;
|
||||
}
|
||||
if ( !hide ) {
|
||||
register char *tokeep ;
|
||||
tokeep=keeps(argp) ;
|
||||
if ( argp[1]=='R' ) {
|
||||
do_Rflag(tokeep);
|
||||
} else {
|
||||
*tokeep |= NO_SCAN ;
|
||||
}
|
||||
l_add(&flags,tokeep) ;
|
||||
}
|
||||
if ( argp[2] && !eaten ) {
|
||||
werror("Unexpected characters at end of %s",argp) ;
|
||||
}
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
firstarg(argp) register char *argp ; {
|
||||
register char *name ;
|
||||
|
||||
name=strrindex(argp,'/') ;
|
||||
if ( name && *(name+1) ) {
|
||||
name++ ;
|
||||
} else {
|
||||
name= argp ;
|
||||
}
|
||||
callname= name;
|
||||
}
|
||||
|
||||
/************************* argument processing ***********************/
|
||||
|
||||
process(arg) char *arg ; {
|
||||
/* Process files & library arguments */
|
||||
trf *phase ;
|
||||
register trf *tmp ;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( debug ) vprint("Processing %s\n",arg) ;
|
||||
#endif
|
||||
p_suffix= strrindex(arg,SUFCHAR) ;
|
||||
orig.p_keep= YES ; /* Don't throw away the original ! */
|
||||
orig.p_keeps= NO;
|
||||
orig.p_path= arg ;
|
||||
if ( arg[0]=='-' || !p_suffix ) {
|
||||
if ( linker ) add_input(&orig,linker) ;
|
||||
return 1 ;
|
||||
}
|
||||
if ( p_basename ) throws(p_basename) ;
|
||||
p_basename= keeps(basename(arg)) ;
|
||||
/* Try to find a path through the transformations */
|
||||
switch( getpath(&phase) ) {
|
||||
case F_NOPATH :
|
||||
error("Cannot produce the desired file from %s",arg) ;
|
||||
if ( linker ) add_input(&orig,linker) ;
|
||||
return 1 ;
|
||||
case F_NOMATCH :
|
||||
if ( stopsuffix ) werror("Unknown suffix in %s",arg) ;
|
||||
if ( linker ) add_input(&orig,linker) ;
|
||||
return 1 ;
|
||||
case F_OK :
|
||||
break ;
|
||||
}
|
||||
if ( !phase ) return 1 ;
|
||||
for ( tmp=phase ; tmp ; tmp=tmp->t_next )
|
||||
if ( !tmp->t_visited ) {
|
||||
/* The flags are set up once.
|
||||
At the first time each phase is in a list.
|
||||
The program name and flags may already be touched
|
||||
by vieuwargs.
|
||||
*/
|
||||
tmp->t_visited=YES ;
|
||||
if ( tmp->t_priority<0 )
|
||||
werror("Using phase %s (negative priority)",
|
||||
tmp->t_name) ;
|
||||
if ( !rts && tmp->t_rts ) rts= tmp->t_rts ;
|
||||
if ( tmp->t_needed ) {
|
||||
add_head(tmp->t_needed) ;
|
||||
add_tail(tmp->t_needed) ;
|
||||
}
|
||||
}
|
||||
if ( phase->t_combine ) {
|
||||
add_input(&orig,phase) ;
|
||||
return 1 ;
|
||||
}
|
||||
in= orig ;
|
||||
if ( !nill_flag && arg_count > 1 ) {
|
||||
printf("%s\n",arg) ;
|
||||
}
|
||||
return startrf(phase) ;
|
||||
}
|
||||
|
||||
int startrf(first) trf *first ; {
|
||||
/* Start the transformations at the indicated phase */
|
||||
register trf *phase ;
|
||||
|
||||
phase=first ;
|
||||
for(;;) {
|
||||
int do_preprocess = 0;
|
||||
int only_prep = 0;
|
||||
|
||||
switch ( phase->t_prep ) {
|
||||
/* BEWARE, sign extension */
|
||||
case NO : break ;
|
||||
default : if ( !mayprep() ) break ;
|
||||
case YES: do_preprocess = 1;
|
||||
break;
|
||||
}
|
||||
if ( cpp_trafo && stopsuffix &&
|
||||
strcmp(cpp_trafo->t_out,stopsuffix)==0 ) {
|
||||
/* user explicitly asked for preprocessing */
|
||||
do_preprocess = 1;
|
||||
only_prep = 1;
|
||||
}
|
||||
|
||||
if (do_preprocess && !transform(cpp_trafo) ) {
|
||||
n_error++ ;
|
||||
#ifdef DEBUG
|
||||
vprint("Pre-processor failed\n") ;
|
||||
#endif
|
||||
return 0 ;
|
||||
}
|
||||
if ( only_prep ) {
|
||||
break ;
|
||||
}
|
||||
if ( !transform(phase) ) {
|
||||
n_error++ ;
|
||||
block(phase->t_next) ;
|
||||
#ifdef DEBUG
|
||||
if ( debug ) {
|
||||
if ( !orig.p_path ) {
|
||||
vprint("phase %s failed\n",
|
||||
phase->t_name ) ;
|
||||
} else {
|
||||
vprint("phase %s for %s failed\n",
|
||||
phase->t_name,orig.p_path) ;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0 ;
|
||||
}
|
||||
first=NO ;
|
||||
phase=phase->t_next ;
|
||||
if ( !phase ) {
|
||||
#ifdef DEBUG
|
||||
if ( debug ) vprint("Transformation sequence complete for %s\n",
|
||||
orig.p_path) ;
|
||||
#endif
|
||||
/* No more work on this file */
|
||||
if ( !in.p_keep ) {
|
||||
fatal("attempt to discard the result file") ;
|
||||
}
|
||||
if ( in.p_keeps ) throws(in.p_path) ;
|
||||
in.p_keep=NO ; in.p_keeps=NO ; in.p_path= (char *) 0 ;
|
||||
return 1 ;
|
||||
}
|
||||
if ( phase->t_combine ) {
|
||||
add_input(&in,phase) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
block(first) trf *first ; {
|
||||
/* One of the input files of this phase could not be produced,
|
||||
block all combiners taking their input from this one.
|
||||
*/
|
||||
register trf *phase ;
|
||||
for ( phase=first ; phase ; phase=phase->t_next ) {
|
||||
if ( phase->t_combine ) phase->t_blocked=YES ;
|
||||
}
|
||||
}
|
||||
mayprep() {
|
||||
int file ;
|
||||
char fc ;
|
||||
file=open(in.p_path,0);
|
||||
if ( file<0 ) return 0 ;
|
||||
if ( read(file,&fc,1)!=1 ) fc=0 ;
|
||||
close(file) ;
|
||||
return fc=='#' ;
|
||||
}
|
||||
|
||||
keephead(suffix) char *suffix ; {
|
||||
l_add(&head_list, suffix) ;
|
||||
}
|
||||
|
||||
keeptail(suffix) char *suffix ; {
|
||||
l_add(&tail_list, suffix) ;
|
||||
}
|
||||
|
||||
scanneeds() {
|
||||
register list_elem *elem ;
|
||||
scanlist(l_first(head_list), elem) { setneeds(l_content(*elem),0) ; }
|
||||
l_clear(&head_list) ;
|
||||
scanlist(l_first(tail_list), elem) { setneeds(l_content(*elem),1) ; }
|
||||
l_clear(&tail_list) ;
|
||||
}
|
||||
|
||||
setneeds(suffix,tail) char *suffix ; {
|
||||
trf *phase ;
|
||||
|
||||
p_suffix= suffix ;
|
||||
switch ( getpath(&phase) ) {
|
||||
case F_OK :
|
||||
for ( ; phase ; phase= phase->t_next ) {
|
||||
if ( phase->t_needed ) {
|
||||
if ( tail )
|
||||
add_tail(phase->t_needed) ;
|
||||
else
|
||||
add_head(phase->t_needed) ;
|
||||
}
|
||||
}
|
||||
break ;
|
||||
case F_NOMATCH :
|
||||
werror("\"%s\": unrecognized suffix",suffix) ;
|
||||
break ;
|
||||
case F_NOPATH :
|
||||
werror("sorry, cannot produce the desired file(s) from %s files",
|
||||
suffix) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
*
|
||||
* This product is part of the Amsterdam Compiler Kit.
|
||||
*
|
||||
* Permission to use, sell, duplicate or disclose this software must be
|
||||
* obtained in writing. Requests for such permissions may be sent to
|
||||
*
|
||||
* Dr. Andrew S. Tanenbaum
|
||||
* Wiskundig Seminarium
|
||||
* Vrije Universiteit
|
||||
* Postbox 7161
|
||||
* 1007 MC Amsterdam
|
||||
* The Netherlands
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "ack.h"
|
||||
#ifdef DEBUG
|
||||
#define ASSERT(p) if(!(p))botch("p");else
|
||||
botch(s)
|
||||
char *s;
|
||||
{
|
||||
printf("malloc/free botched: %s\n",s);
|
||||
abort();
|
||||
}
|
||||
#else
|
||||
#define ASSERT(p)
|
||||
#endif
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Header$" ;
|
||||
#endif
|
||||
|
||||
/* avoid break bug */
|
||||
#ifdef pdp11
|
||||
#define GRANULE 64
|
||||
#else
|
||||
#define GRANULE 0
|
||||
#endif
|
||||
/* C storage allocator
|
||||
* circular first-fit strategy
|
||||
* works with noncontiguous, but monotonically linked, arena
|
||||
* each block is preceded by a ptr to the (pointer of)
|
||||
* the next following block
|
||||
* blocks are exact number of words long
|
||||
* aligned to the data type requirements of ALIGN
|
||||
* pointers to blocks must have BUSY bit 0
|
||||
* bit in ptr is 1 for busy, 0 for idle
|
||||
* gaps in arena are merely noted as busy blocks
|
||||
* last block of arena (pointed to by alloct) is empty and
|
||||
* has a pointer to first
|
||||
* idle blocks are coalesced during space search
|
||||
*
|
||||
* a different implementation may need to redefine
|
||||
* ALIGN, NALIGN, BLOCK, BUSY, INT
|
||||
* where INT is integer type to which a pointer can be cast
|
||||
*/
|
||||
#define INT int
|
||||
#define ALIGN int
|
||||
#define NALIGN 1
|
||||
#define WORD sizeof(union store)
|
||||
#define BLOCK 1024 /* a multiple of WORD*/
|
||||
#define BUSY 1
|
||||
#define NULL 0
|
||||
#define testbusy(p) ((INT)(p)&BUSY)
|
||||
#define setbusy(p) (union store *)((INT)(p)|BUSY)
|
||||
#define clearbusy(p) (union store *)((INT)(p)&~BUSY)
|
||||
|
||||
union store { union store *ptr;
|
||||
ALIGN dummy[NALIGN];
|
||||
int calloc; /*calloc clears an array of integers*/
|
||||
};
|
||||
|
||||
static union store allocs[2]; /*initial arena*/
|
||||
static union store *allocp; /*search ptr*/
|
||||
static union store *alloct; /*arena top*/
|
||||
static union store *allocx; /*for benefit of realloc*/
|
||||
char *sbrk();
|
||||
|
||||
char *
|
||||
malloc(nbytes)
|
||||
unsigned nbytes;
|
||||
{
|
||||
register union store *p, *q;
|
||||
register nw;
|
||||
static temp; /*coroutines assume no auto*/
|
||||
|
||||
if(allocs[0].ptr==0) { /*first time*/
|
||||
allocs[0].ptr = setbusy(&allocs[1]);
|
||||
allocs[1].ptr = setbusy(&allocs[0]);
|
||||
alloct = &allocs[1];
|
||||
allocp = &allocs[0];
|
||||
}
|
||||
nw = (nbytes+WORD+WORD-1)/WORD;
|
||||
ASSERT(allocp>=allocs && allocp<=alloct);
|
||||
ASSERT(allock());
|
||||
for(p=allocp; ; ) {
|
||||
for(temp=0; ; ) {
|
||||
if(!testbusy(p->ptr)) {
|
||||
while(!testbusy((q=p->ptr)->ptr)) {
|
||||
ASSERT(q>p&&q<alloct);
|
||||
p->ptr = q->ptr;
|
||||
}
|
||||
if(q>=p+nw && p+nw>=p)
|
||||
goto found;
|
||||
}
|
||||
q = p;
|
||||
p = clearbusy(p->ptr);
|
||||
if(p>q)
|
||||
ASSERT(p<=alloct);
|
||||
else if(q!=alloct || p!=allocs) {
|
||||
ASSERT(q==alloct&&p==allocs);
|
||||
return(NULL);
|
||||
} else if(++temp>1)
|
||||
break;
|
||||
}
|
||||
temp = ((nw+BLOCK/WORD)/(BLOCK/WORD))*(BLOCK/WORD);
|
||||
q = (union store *)sbrk(0);
|
||||
if(q+temp+GRANULE < q) {
|
||||
return(NULL);
|
||||
}
|
||||
q = (union store *)sbrk(temp*WORD);
|
||||
if((INT)q == -1) {
|
||||
return(NULL);
|
||||
}
|
||||
ASSERT(q>alloct);
|
||||
alloct->ptr = q;
|
||||
if(q!=alloct+1)
|
||||
alloct->ptr = setbusy(alloct->ptr);
|
||||
alloct = q->ptr = q+temp-1;
|
||||
alloct->ptr = setbusy(allocs);
|
||||
}
|
||||
found:
|
||||
allocp = p + nw;
|
||||
ASSERT(allocp<=alloct);
|
||||
if(q>allocp) {
|
||||
allocx = allocp->ptr;
|
||||
allocp->ptr = p->ptr;
|
||||
}
|
||||
p->ptr = setbusy(allocp);
|
||||
return((char *)(p+1));
|
||||
}
|
||||
|
||||
/* freeing strategy tuned for LIFO allocation
|
||||
*/
|
||||
free(ap)
|
||||
register char *ap;
|
||||
{
|
||||
register union store *p = (union store *)ap;
|
||||
|
||||
ASSERT(p>clearbusy(allocs[1].ptr)&&p<=alloct);
|
||||
ASSERT(allock());
|
||||
allocp = --p;
|
||||
ASSERT(testbusy(p->ptr));
|
||||
p->ptr = clearbusy(p->ptr);
|
||||
ASSERT(p->ptr > allocp && p->ptr <= alloct);
|
||||
}
|
||||
|
||||
/* realloc(p, nbytes) reallocates a block obtained from malloc()
|
||||
* and freed since last call of malloc()
|
||||
* to have new size nbytes, and old content
|
||||
* returns new location, or 0 on failure
|
||||
*/
|
||||
|
||||
char *
|
||||
realloc(p, nbytes)
|
||||
register union store *p;
|
||||
unsigned nbytes;
|
||||
{
|
||||
register union store *q;
|
||||
union store *s, *t;
|
||||
register unsigned nw;
|
||||
unsigned onw;
|
||||
|
||||
if(testbusy(p[-1].ptr))
|
||||
free((char *)p);
|
||||
onw = p[-1].ptr - p;
|
||||
q = (union store *)malloc(nbytes);
|
||||
if(q==NULL || q==p)
|
||||
return((char *)q);
|
||||
s = p;
|
||||
t = q;
|
||||
nw = (nbytes+WORD-1)/WORD;
|
||||
if(nw<onw)
|
||||
onw = nw;
|
||||
while(onw--!=0)
|
||||
*t++ = *s++;
|
||||
if(q<p && q+nw>=p)
|
||||
(q+(q+nw-p))->ptr = allocx;
|
||||
return((char *)q);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
allock()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
register union store *p;
|
||||
int x;
|
||||
x = 0;
|
||||
for(p= &allocs[0]; clearbusy(p->ptr) > p; p=clearbusy(p->ptr)) {
|
||||
if(p==allocp)
|
||||
x++;
|
||||
}
|
||||
ASSERT(p==alloct);
|
||||
return(x==1|p==allocp);
|
||||
#else
|
||||
return(1);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
char *fname = 0 ;
|
||||
char dname[200] ;
|
||||
char *tail ;
|
||||
|
||||
FILE *intab ;
|
||||
FILE *dmach ;
|
||||
|
||||
int index ;
|
||||
|
||||
main(argc,argv) char **argv ; {
|
||||
register i ;
|
||||
|
||||
start(argv[1]) ;
|
||||
for ( i=2 ; i<argc ; i++ ) {
|
||||
fname= argv[i] ;
|
||||
readm() ;
|
||||
}
|
||||
stop(argc>2) ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
start(dir) char *dir ; {
|
||||
tail= dname ;
|
||||
while ( *dir ) {
|
||||
*tail++ = *dir ++ ;
|
||||
}
|
||||
if ( tail!=dname ) *tail++= '/' ;
|
||||
index=0 ;
|
||||
intab= fopen("intable.c","w");
|
||||
dmach= fopen("dmach.c","w");
|
||||
if ( intab==NULL || dmach==NULL ) {
|
||||
fprintf(stderr,"Couln't create output file(s)\n");
|
||||
exit ( 1) ;
|
||||
}
|
||||
fprintf(dmach,"#include \"dmach.h\"\n\ndmach\tmassoc[] = {\n") ;
|
||||
fprintf(intab,"char intable[] = {\n") ;
|
||||
}
|
||||
|
||||
stop(filled) {
|
||||
fprintf(dmach,"\t{\"\",\t-1\t}\n} ;\n") ;
|
||||
if ( !filled ) fprintf(intab,"\t0\n") ;
|
||||
fprintf(intab,"\n} ;\n") ;
|
||||
fclose(dmach); fclose(intab) ;
|
||||
}
|
||||
|
||||
FILE *do_open(file) char *file ; {
|
||||
FILE *fd;
|
||||
|
||||
strcpy(tail,file) ;
|
||||
strcat(tail,"/");
|
||||
strcat(tail,"descr");
|
||||
if ((fd = fopen(dname,"r")) != NULL) return fd;
|
||||
strcpy(tail,"descr/");
|
||||
strcat(tail,file);
|
||||
return fopen(dname,"r");
|
||||
}
|
||||
|
||||
readm() {
|
||||
register int i ;
|
||||
register int token ;
|
||||
register FILE *in ;
|
||||
|
||||
in=do_open(fname) ;
|
||||
if ( in==NULL ) {
|
||||
fprintf(stderr,"Cannot open %s\n",fname) ;
|
||||
return ;
|
||||
}
|
||||
i=0 ;
|
||||
fprintf(dmach,"\t{\"%s\",\t%d\t},\n",fname,index) ;
|
||||
fprintf(intab,"\n/* %s */\n\t",fname) ;
|
||||
for (;;) {
|
||||
token=getc(in) ;
|
||||
index++ ;
|
||||
if ( ++i == 10 ) {
|
||||
fprintf(intab,"\n\t") ;
|
||||
i=0 ;
|
||||
} else {
|
||||
fprintf(intab," ") ;
|
||||
}
|
||||
if ( !isascii(token) || !(isprint(token) || isspace(token)) ){
|
||||
if ( token!=EOF ) {
|
||||
fprintf(stderr,"warning: non-ascii in %s\n",fname) ;
|
||||
fprintf(intab,"%4d,",token) ;
|
||||
} else {
|
||||
fprintf(intab," 0,",token) ;
|
||||
break ;
|
||||
}
|
||||
} else if ( isprint(token) ) {
|
||||
switch ( token ) {
|
||||
case '\'': fprintf(intab,"'\\''") ; break ;
|
||||
case '\\': fprintf(intab,"'\\\\'") ; break ;
|
||||
default: fprintf(intab," '%c'",token) ; break ;
|
||||
}
|
||||
} else switch ( token ) {
|
||||
case '\n' : fprintf(intab,"'\\n'") ; break ;
|
||||
case '\t' : fprintf(intab,"'\\t'") ; break ;
|
||||
case '\r' : fprintf(intab,"'\\r'") ; break ;
|
||||
case '\f' : fprintf(intab,"'\\f'") ; break ;
|
||||
case ' ' : fprintf(intab," ' '") ; break ;
|
||||
default : fprintf(stderr,"warning: unrec. %d\n",
|
||||
token) ;
|
||||
fprintf(intab,"%4d",token) ;
|
||||
break ;
|
||||
}
|
||||
fprintf(intab,",") ;
|
||||
}
|
||||
fclose(in) ;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
Makefile
|
||||
em_pc.c
|
||||
@@ -1,28 +0,0 @@
|
||||
EMHOME=../../..
|
||||
h=$(EMHOME)/h
|
||||
|
||||
PC_PATH=$(EMHOME)/lib/em_pc
|
||||
|
||||
LDFLAGS = -i
|
||||
|
||||
em_pc: em_pc.c $h/local.h $h/em_path.h
|
||||
$(CC) $(LDFLAGS) -o em_pc -O -I$h em_pc.c
|
||||
|
||||
cmp: em_pc
|
||||
cmp em_pc $(PC_PATH)
|
||||
|
||||
install: em_pc
|
||||
rm -f $(PC_PATH)
|
||||
cp em_pc $(PC_PATH)
|
||||
|
||||
lint:
|
||||
lint -hpxc -I$h em_pc.c
|
||||
|
||||
clean:
|
||||
rm -f *.o *.old em_pc
|
||||
|
||||
opr:
|
||||
make pr ^ opr
|
||||
|
||||
pr:
|
||||
pr -n em_pc.c
|
||||
@@ -1,705 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
/* $Header$ */
|
||||
|
||||
/*
|
||||
* put all the pieces of the pascal part of the EM project together
|
||||
* original author: Johan Stevenson, Vrije Universiteit, Amsterdam
|
||||
* heavily modified by: Ed Keizer, Vrije Universiteit, Amsterdam
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/dir.h>
|
||||
#include <em_path.h>
|
||||
#include <pc_size.h>
|
||||
#include <local.h>
|
||||
|
||||
#define MAX_FLAG 40 /* The Max. no of '{' flags allowed */
|
||||
|
||||
#define void int
|
||||
|
||||
char *pc_path;
|
||||
char *err_path;
|
||||
|
||||
int toterr;
|
||||
int parent;
|
||||
|
||||
char *eeflag;
|
||||
int no_pemflag = 0 ;
|
||||
char *pemflag[MAX_FLAG];
|
||||
char *eflag;
|
||||
char *wflag;
|
||||
|
||||
int sizes[sz_last+1] = {
|
||||
4, /* sz_addr */
|
||||
8, /* sz_real */
|
||||
0, /* sz_head */
|
||||
512, /* sz_buff */
|
||||
4096, /* sz_mset */
|
||||
4, /* sz_iset */
|
||||
4, /* sz_word */
|
||||
4, /* sz_int */
|
||||
4, /* sz_long */
|
||||
};
|
||||
|
||||
#define CALLSIZE 60
|
||||
char *callvector[CALLSIZE];
|
||||
char **av;
|
||||
int ac;
|
||||
int fileargs; /* number of recognized, processed args */
|
||||
int flagargs;
|
||||
char *progname;
|
||||
char *source;
|
||||
|
||||
#define CHARSIZE 2500
|
||||
#define CHARMARG 50
|
||||
char charbuf[CHARSIZE];
|
||||
char *charp = charbuf;
|
||||
|
||||
char *tmp_dir = TMP_DIR;
|
||||
char *unique = "pcXXXXXX";
|
||||
|
||||
char sigs[] = {
|
||||
SIGHUP,
|
||||
SIGINT,
|
||||
SIGTERM,
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* forward function declarations
|
||||
*/
|
||||
void finish();
|
||||
void pem();
|
||||
int list();
|
||||
char *flag();
|
||||
char *tempfile();
|
||||
char **initvector();
|
||||
char *basename();
|
||||
|
||||
/*
|
||||
* used library routines and data
|
||||
*/
|
||||
|
||||
extern char *sys_errlist[];
|
||||
extern int errno;
|
||||
|
||||
int atoi();
|
||||
void exit();
|
||||
void sleep();
|
||||
void execv();
|
||||
char *malloc();
|
||||
int chdir();
|
||||
int fork();
|
||||
int wait();
|
||||
int getpid();
|
||||
int open();
|
||||
int close();
|
||||
int read();
|
||||
|
||||
main(argc,argv) char **argv; {
|
||||
register char *p;
|
||||
char *files[3] ;
|
||||
|
||||
for (p = sigs; *p; p++)
|
||||
if (signal(*p,finish) == SIG_IGN)
|
||||
signal(*p,SIG_IGN);
|
||||
ac = argc;
|
||||
av = argv;
|
||||
progname = *av++;
|
||||
init();
|
||||
while ( --ac>0 ) {
|
||||
p = *av++;
|
||||
if (*p == '-') {
|
||||
flagargs++;
|
||||
p = flag(p);
|
||||
} else {
|
||||
if ( fileargs>=3 ) fatal("Too many file arguments") ;
|
||||
files[fileargs++]= p;
|
||||
}
|
||||
}
|
||||
if ( fileargs!=3 ) fatal("Not enough arguments") ;
|
||||
source=files[2] ;
|
||||
pem(files[0],files[1]) ;
|
||||
finish();
|
||||
}
|
||||
|
||||
char *flag(f) char *f; {
|
||||
register char *p;
|
||||
|
||||
p = f+1;
|
||||
switch (*p++) {
|
||||
case 'e':
|
||||
eflag = f;
|
||||
break;
|
||||
case 'E':
|
||||
eeflag = f;
|
||||
break;
|
||||
case 'w':
|
||||
wflag = f;
|
||||
break;
|
||||
case 'V':
|
||||
initsizes(f+2);
|
||||
return(0);
|
||||
case '{':
|
||||
if ( no_pemflag>=MAX_FLAG ) {
|
||||
ermess("too many flags, ignored %s",f) ;
|
||||
} else {
|
||||
pemflag[no_pemflag++] = p;
|
||||
}
|
||||
return(0);
|
||||
case 'R':
|
||||
pc_path= p ;
|
||||
return 0 ;
|
||||
case 'r' :
|
||||
err_path= p ;
|
||||
return 0 ;
|
||||
default:
|
||||
return(f);
|
||||
}
|
||||
if (*p)
|
||||
fatal("bad flag %s",f);
|
||||
return(0);
|
||||
}
|
||||
|
||||
initsizes(vvflag) char *vvflag; {
|
||||
register c, i;
|
||||
register char *p = vvflag;
|
||||
|
||||
while (c = *p++) {
|
||||
i = atoi(p);
|
||||
while (*p >= '0' && *p <= '9')
|
||||
p++;
|
||||
switch (c) {
|
||||
case 'p': sz_addr = i; continue;
|
||||
case 'f': sz_real = i; continue;
|
||||
case 'h': sz_head = i; continue;
|
||||
case 'b': sz_buff = i; continue;
|
||||
case 'm': sz_mset = i; continue;
|
||||
case 'j': sz_iset = i; continue;
|
||||
case 'w': sz_word = i; continue;
|
||||
case 'i': sz_int = i; continue;
|
||||
case 'l': sz_long = i; continue;
|
||||
}
|
||||
fatal("bad V-flag %s",vvflag);
|
||||
}
|
||||
if (sz_word != sz_int ||
|
||||
(sz_int != 2 && sz_int != 4) ||
|
||||
(sz_long != 4)) {
|
||||
fatal("bad V-flag %s",vvflag);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------ calling sequences -------------------- */
|
||||
|
||||
pem(p,q) char *p,*q; {
|
||||
register char **v,*d;
|
||||
int i;
|
||||
FILE *erfil;
|
||||
|
||||
if ( !pc_path ) fatal("Missing compiler pathname specification\n") ;
|
||||
v = initvector(pc_path);
|
||||
d = tempfile('d');
|
||||
if ((erfil = fopen(d,"w")) == NULL)
|
||||
syserr(d);
|
||||
if (sz_head == 0)
|
||||
sz_head = 6*sz_word + 2*sz_addr;
|
||||
for (i = 0; i <= sz_last; i++)
|
||||
fprintf(erfil, "%d\n",sizes[i]);
|
||||
fprintf(erfil,"%s\n",basename(source));
|
||||
for ( i=0 ; i<no_pemflag ; i++ ) fprintf(erfil,"%s\n",pemflag[i]);
|
||||
fclose(erfil);
|
||||
*v++ = q;
|
||||
*v++ = d;
|
||||
call(v,p,(char *)0);
|
||||
if (toterr == 0)
|
||||
if (list(p,d) < 0)
|
||||
toterr++;
|
||||
donewith(d);
|
||||
}
|
||||
|
||||
/* ------------------- miscellaneous routines --------------- */
|
||||
|
||||
char *basename(p) char *p; {
|
||||
register char *q;
|
||||
|
||||
q = p;
|
||||
while (*q)
|
||||
if (*q++ == '/')
|
||||
p = q;
|
||||
return(p);
|
||||
}
|
||||
|
||||
char *tempfile(suf) {
|
||||
register char *p,*q;
|
||||
register i;
|
||||
|
||||
p = charp; q = tmp_dir;
|
||||
while (*p = *q++)
|
||||
p++;
|
||||
*p++ = '/';
|
||||
q = unique;
|
||||
while (*p = *q++)
|
||||
p++;
|
||||
i = fileargs;
|
||||
do
|
||||
*p++ = i % 10 + '0';
|
||||
while (i /= 10);
|
||||
*p++ = '.'; *p++ = suf; *p++ = '\0';
|
||||
q = charp; charp = p;
|
||||
return(q);
|
||||
}
|
||||
|
||||
call(v,in,out) char **v,*in,*out; {
|
||||
register pid;
|
||||
int status;
|
||||
|
||||
while ((parent = fork()) < 0)
|
||||
sleep(1);
|
||||
if (parent == 0) {
|
||||
if (in) {
|
||||
close(0);
|
||||
if (open(in,0) != 0)
|
||||
syserr(in);
|
||||
}
|
||||
if (out) {
|
||||
close(1);
|
||||
if (creat(out,0666) != 1)
|
||||
syserr(out);
|
||||
}
|
||||
*v = 0;
|
||||
execv(callvector[0],callvector+1);
|
||||
syserr(callvector[0]);
|
||||
}
|
||||
while ((pid = wait(&status)) != parent) {
|
||||
if (pid == -1)
|
||||
fatal("process %d disappeared",parent);
|
||||
fatal("unknown child %d died",pid);
|
||||
}
|
||||
if ((status & 0177) > 3) {
|
||||
/*
|
||||
if ((status & 0200) && tflag==0)
|
||||
unlink("core");
|
||||
*/
|
||||
fatal("signal %d in %s. Ask an expert for help",
|
||||
status&0177,callvector[0]);
|
||||
}
|
||||
if (status & 0177400)
|
||||
toterr++;
|
||||
}
|
||||
|
||||
char **initvector(path) char *path; {
|
||||
register char *p,**v;
|
||||
|
||||
v = callvector;
|
||||
p = path;
|
||||
*v++ = p;
|
||||
*v++ = basename(p);
|
||||
return(v);
|
||||
}
|
||||
|
||||
finish() {
|
||||
register char *p,*q;
|
||||
register fd;
|
||||
struct direct dir;
|
||||
|
||||
signal(SIGINT,SIG_IGN);
|
||||
if (parent != 0) {
|
||||
chdir(tmp_dir);
|
||||
fd = open(".",0);
|
||||
while (read(fd,(char *) &dir,sizeof dir) == sizeof dir) {
|
||||
if (dir.d_ino == 0)
|
||||
continue;
|
||||
p = unique;
|
||||
q = dir.d_name;
|
||||
while (*p++ == *q++)
|
||||
if (*p == '\0') {
|
||||
unlink(dir.d_name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
exit(toterr ? -1 : 0);
|
||||
}
|
||||
|
||||
|
||||
donewith(p) char *p; {
|
||||
|
||||
if (p >= charbuf && p < &charbuf[CHARSIZE])
|
||||
unlink(p);
|
||||
}
|
||||
|
||||
init() {
|
||||
register char *p;
|
||||
register i,fd;
|
||||
|
||||
if ((fd = open(tmp_dir,0)) < 0)
|
||||
tmp_dir = ".";
|
||||
close(fd);
|
||||
p = unique+2;
|
||||
parent = i = getpid();
|
||||
do
|
||||
*p++ = i % 10 + '0';
|
||||
while (i /= 10);
|
||||
*p++ = '.'; *p = '\0';
|
||||
}
|
||||
|
||||
/* ------------------- pascal listing ----------------------- */
|
||||
|
||||
#define MAXERNO 300
|
||||
#define MAXERRLIST 10
|
||||
#define IDMAX 8
|
||||
|
||||
struct errec {
|
||||
int erno;
|
||||
char mess[IDMAX+1];
|
||||
int mesi;
|
||||
int chno;
|
||||
int lino;
|
||||
};
|
||||
|
||||
struct errec curr;
|
||||
struct errec next;
|
||||
|
||||
int *index = 0;
|
||||
int maxerno;
|
||||
|
||||
int errerr;
|
||||
int errfat;
|
||||
|
||||
int listlino;
|
||||
int listorig;
|
||||
int listrela;
|
||||
char *listfnam;
|
||||
|
||||
FILE *inpfil;
|
||||
FILE *mesfil;
|
||||
FILE *errfil;
|
||||
|
||||
int errorline();
|
||||
int geterrec();
|
||||
int nexterror();
|
||||
|
||||
int list(p,q) char *p,*q; {
|
||||
|
||||
if ((errfil = fopen(q,"r")) == NULL)
|
||||
syserr(q);
|
||||
if (geterrec() == 0)
|
||||
if (eeflag==0) {
|
||||
fclose(errfil);
|
||||
return(0);
|
||||
}
|
||||
if (index == 0) {
|
||||
index = (int *) malloc(MAXERNO * sizeof index[0]);
|
||||
fillindex();
|
||||
}
|
||||
if ((inpfil = fopen(p,"r")) == NULL)
|
||||
syserr(p);
|
||||
errerr = 0;
|
||||
errfat = 0;
|
||||
listlino = 0;
|
||||
listorig = 0;
|
||||
listrela = 0;
|
||||
listfnam = source;
|
||||
if (eeflag)
|
||||
listfull();
|
||||
else if (eflag)
|
||||
listpartial();
|
||||
else
|
||||
listshort();
|
||||
fclose(errfil);
|
||||
fclose(inpfil);
|
||||
fflush(stdout);
|
||||
return(errfat ? -1 : 1);
|
||||
}
|
||||
|
||||
listshort() {
|
||||
|
||||
while (nexterror()) {
|
||||
while (listlino < curr.lino)
|
||||
nextline(0);
|
||||
printf("%s, line %d: ",listfnam,listrela);
|
||||
string(&curr);
|
||||
}
|
||||
}
|
||||
|
||||
listfull() {
|
||||
|
||||
if (nexterror())
|
||||
do {
|
||||
do {
|
||||
nextline(1);
|
||||
} while (listlino < curr.lino);
|
||||
} while (errorline());
|
||||
while (nextline(1))
|
||||
;
|
||||
}
|
||||
|
||||
listpartial() {
|
||||
|
||||
if (nexterror())
|
||||
do {
|
||||
do {
|
||||
nextline(listlino >= curr.lino-2);
|
||||
} while (listlino < curr.lino);
|
||||
} while (errorline());
|
||||
}
|
||||
|
||||
int nextline(printing) {
|
||||
register ch;
|
||||
|
||||
listlino++;
|
||||
ch = getc(inpfil);
|
||||
while (ch == '#') {
|
||||
if (lineline(printing) == 1)
|
||||
return(1);
|
||||
ch = getc(inpfil);
|
||||
}
|
||||
listrela++;
|
||||
if (listfnam == source)
|
||||
listorig++;
|
||||
if (ch != EOF) {
|
||||
if (printing)
|
||||
printf("%5d\t",listorig);
|
||||
do {
|
||||
if (printing)
|
||||
putchar(ch);
|
||||
if (ch == '\n')
|
||||
return(1);
|
||||
} while ((ch = getc(inpfil)) != EOF);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
lineline(printing) {
|
||||
register ch;
|
||||
register char *p,*q;
|
||||
static char line[100];
|
||||
int ln;
|
||||
|
||||
p = line;
|
||||
while ((ch = getc(inpfil)) != '\n') {
|
||||
if (ch == EOF || p == &line[100-1]) {
|
||||
*p = 0;
|
||||
listlino++;
|
||||
listrela++;
|
||||
if (listfnam == source)
|
||||
listorig++;
|
||||
if (printing) {
|
||||
printf("%5d\t#%s", listorig, p);
|
||||
putchar(ch);
|
||||
}
|
||||
while (ch != EOF && ch != '\n') {
|
||||
ch = getc(inpfil);
|
||||
if (ch != EOF && printing) putchar(ch);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
*p++ = ch;
|
||||
}
|
||||
*p = '\0'; p = line;
|
||||
ln = atoi(p)-1;
|
||||
if (ln >= 0) {
|
||||
while ((ch = *p++) != '"' && ch != '\0')
|
||||
;
|
||||
if (ch == '"') {
|
||||
q = p;
|
||||
while (ch = *p++) {
|
||||
if (ch == '"') {
|
||||
*--p = '\0';
|
||||
listrela = ln;
|
||||
if ( source ) {
|
||||
listfnam = strcmp(q,source)==0 ? source : q;
|
||||
}
|
||||
else {
|
||||
source=q ; listfnam=q ;
|
||||
}
|
||||
listlino++;
|
||||
if (printing)
|
||||
printf("\t#%s\n",p);
|
||||
return 1 ;
|
||||
}
|
||||
if (ch == '/')
|
||||
q = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
listlino++;
|
||||
listrela++;
|
||||
if (listfnam == source)
|
||||
listorig++;
|
||||
if (printing)
|
||||
printf("%5d\t#%s\n",listorig, p);
|
||||
return(0);
|
||||
}
|
||||
|
||||
int errorline() {
|
||||
register c;
|
||||
register struct errec *p,*q;
|
||||
struct errec lerr[MAXERRLIST];
|
||||
int goon;
|
||||
|
||||
printf("*** ***");
|
||||
p = lerr;
|
||||
c = 0;
|
||||
do {
|
||||
if (c < curr.chno) {
|
||||
printf("%*c",curr.chno-c,'^');
|
||||
c = curr.chno;
|
||||
}
|
||||
if (p < &lerr[MAXERRLIST])
|
||||
*p++ = curr;
|
||||
goon = nexterror();
|
||||
} while (goon && curr.lino==listlino);
|
||||
putchar('\n');
|
||||
for (q = lerr; q < p; q++)
|
||||
string(q);
|
||||
putchar('\n');
|
||||
return(goon);
|
||||
}
|
||||
|
||||
int geterrec() {
|
||||
register ch;
|
||||
register char *p;
|
||||
|
||||
ch = getc(errfil);
|
||||
next.erno = 0;
|
||||
next.mesi = -1;
|
||||
next.mess[0] = '\0';
|
||||
if (ch == EOF)
|
||||
return(0);
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
ch = getnum(ch,&next.mesi);
|
||||
} else if (ch == '\'') {
|
||||
p = next.mess;
|
||||
while ((ch = getc(errfil)) != ' ' && ch != EOF)
|
||||
if (p < &next.mess[IDMAX])
|
||||
*p++ = ch;
|
||||
*p = '\0';
|
||||
}
|
||||
ch = getnum(ch, &next.erno);
|
||||
ch = getnum(ch, &next.lino);
|
||||
ch = getnum(ch, &next.chno);
|
||||
if (ch != '\n')
|
||||
fatal("bad error line");
|
||||
return(1);
|
||||
}
|
||||
|
||||
int getnum(ch, ip) register ch; register *ip; {
|
||||
register neg;
|
||||
|
||||
*ip = 0;
|
||||
while (ch == ' ')
|
||||
ch = getc(errfil);
|
||||
if (neg = ch=='-')
|
||||
ch = getc(errfil);
|
||||
while (ch >= '0' && ch <= '9') {
|
||||
*ip = *ip * 10 - '0' + ch;
|
||||
ch = getc(errfil);
|
||||
}
|
||||
if (neg)
|
||||
*ip = -(*ip);
|
||||
return(ch);
|
||||
}
|
||||
|
||||
int nexterror() {
|
||||
|
||||
do { /* skip warnings if wflag */
|
||||
curr = next;
|
||||
if (curr.erno == 0)
|
||||
return(0);
|
||||
for (;;) {
|
||||
if (geterrec() == 0)
|
||||
break;
|
||||
if (next.lino != curr.lino || next.chno != curr.chno)
|
||||
break;
|
||||
if (curr.erno < 0 && next.erno > 0)
|
||||
/* promote warnings if they cause fatals */
|
||||
curr.erno = -curr.erno;
|
||||
if (next.mess[0] != '\0' || next.mesi != -1)
|
||||
/* give all parameterized errors */
|
||||
break;
|
||||
if (curr.mess[0] != '\0' || curr.mesi != -1)
|
||||
/* and at least a non-parameterized one */
|
||||
break;
|
||||
}
|
||||
} while (curr.erno < 0 && wflag != 0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
fillindex() {
|
||||
register *ip,n,c;
|
||||
|
||||
if ( !err_path ) fatal("Missing error file name\n") ;
|
||||
if ((mesfil = fopen(err_path,"r")) == NULL)
|
||||
syserr(err_path);
|
||||
ip = index;
|
||||
*ip++ = 0;
|
||||
n = 0;
|
||||
while ((c = getc(mesfil)) != EOF) {
|
||||
n++;
|
||||
if (c == '\n') {
|
||||
*ip++ = n;
|
||||
if (ip > &index[MAXERNO])
|
||||
fatal("too many errors on %s",err_path);
|
||||
}
|
||||
}
|
||||
maxerno = ip - index;
|
||||
}
|
||||
|
||||
string(ep) register struct errec *ep; {
|
||||
register i,n;
|
||||
|
||||
errerr++;
|
||||
if ((i = ep->erno) < 0) {
|
||||
i = -i;
|
||||
printf("Warning: ");
|
||||
} else
|
||||
errfat++;
|
||||
if (i == 0 || i >= maxerno)
|
||||
fatal("bad error number %d",i);
|
||||
n = index[i] - index[i-1];
|
||||
fseek(mesfil,(long)index[i-1],0);
|
||||
while (--n >= 0) {
|
||||
i = getc(mesfil);
|
||||
if (i == '%' && --n>=0) {
|
||||
i = getc(mesfil);
|
||||
if (i == 'i')
|
||||
printf("%d", ep->mesi);
|
||||
else if (i == 's')
|
||||
printf("%s", ep->mess);
|
||||
else
|
||||
putchar(i);
|
||||
} else
|
||||
putchar(i);
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------- error routines -------------------------- */
|
||||
|
||||
/* VARARGS1 */
|
||||
void ermess(s,a1,a2,a3,a4) char *s; {
|
||||
|
||||
fprintf(stderr,"%s: ",progname);
|
||||
fprintf(stderr,s,a1,a2,a3,a4);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
syserr(s) char *s; {
|
||||
fatal("%s: %s",s,sys_errlist[errno]);
|
||||
}
|
||||
|
||||
/* VARARGS1 */
|
||||
void fatal(s,a1,a2,a3,a4) char *s; {
|
||||
|
||||
ermess(s,a1,a2,a3,a4);
|
||||
toterr++;
|
||||
finish();
|
||||
}
|
||||
@@ -1,187 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
#PARAMS do not remove this line!
|
||||
|
||||
SRC_DIR = $(SRC_HOME)/util/ack
|
||||
|
||||
HFILES=\
|
||||
$(SRC_DIR)/ack.h \
|
||||
$(SRC_DIR)/list.h \
|
||||
$(SRC_DIR)/trans.h \
|
||||
$(SRC_DIR)/data.h \
|
||||
$(SRC_DIR)/dmach.h \
|
||||
$(SRC_DIR)/grows.h
|
||||
|
||||
DSRC=\
|
||||
$(SRC_DIR)/list.c \
|
||||
$(SRC_DIR)/data.c \
|
||||
$(SRC_DIR)/main.c \
|
||||
$(SRC_DIR)/scan.c \
|
||||
$(SRC_DIR)/svars.c \
|
||||
$(SRC_DIR)/trans.c \
|
||||
$(SRC_DIR)/util.c \
|
||||
$(SRC_DIR)/rmach.c \
|
||||
$(SRC_DIR)/run.c \
|
||||
$(SRC_DIR)/grows.c \
|
||||
$(SRC_DIR)/files.c
|
||||
|
||||
ISRC=\
|
||||
dmach.c \
|
||||
intable.c
|
||||
|
||||
CFILES = $(DSRC) $(ISRC)
|
||||
|
||||
OBJ=\
|
||||
list.$(SUF) \
|
||||
data.$(SUF) \
|
||||
main.$(SUF) \
|
||||
scan.$(SUF) \
|
||||
svars.$(SUF) \
|
||||
trans.$(SUF) \
|
||||
util.$(SUF) \
|
||||
rmach.$(SUF) \
|
||||
run.$(SUF) \
|
||||
dmach.$(SUF) \
|
||||
intable.$(SUF) \
|
||||
grows.$(SUF) \
|
||||
files.$(SUF)
|
||||
|
||||
ACKDIR=$(TARGET_HOME)/lib
|
||||
FE=fe
|
||||
INTABLES=sun3
|
||||
LNTABLES=acc apc abc ocm m2 f2c vax4 i86 i386 m68k2 m68k4 pmds pmds4 mantra \
|
||||
m68020 z8000 pdp em22 em24 em44 6500 6800 6805 6809 i80 ns s2650 z80 \
|
||||
sun2 xenix3 minix minixST sparc sparc_solaris arm
|
||||
INCLUDES=-I$(TARGET_HOME)/h -I$(TARGET_HOME)/config -I$(SRC_DIR)
|
||||
CFLAGS= $(INCLUDES) $(COPTIONS)
|
||||
UCFLAGS= $(INCLUDES) $(UCOPTIONS)
|
||||
LINTFLAGS= $(INCLUDES) $(LINTOPTIONS)
|
||||
LDFLAGS= $(LDOPTIONS)
|
||||
ULDFLAGS= $(ULDOPTIONS)
|
||||
BINDIR=$(TARGET_HOME)/bin
|
||||
HDIR=$(TARGET_HOME)/h
|
||||
MODDIR=$(TARGET_HOME)/modules/lib
|
||||
|
||||
all: ack ack.1
|
||||
|
||||
install: ack ack.1
|
||||
cp ack $(BINDIR)/ack
|
||||
-cd $(BINDIR) ; \
|
||||
for i in $(INTABLES) $(LNTABLES) ; do rm -f $$i ; ln ack $$i ; done
|
||||
if [ $(DO_MACHINE_INDEP) = y ] ; \
|
||||
then mk_manpage ack.1 $(TARGET_HOME) ; \
|
||||
fi
|
||||
|
||||
cmp: ack
|
||||
-cmp ack $(BINDIR)/ack
|
||||
|
||||
ack.1: $(SRC_DIR)/ack.1.X
|
||||
-sh -c 'tbl < $(SRC_DIR)/ack.1.X > ack.1'
|
||||
-sh -c 'if test -s ack.1 ; then : ; else cp $(SRC_DIR)/ack.1.X ack.1 ; fi'
|
||||
|
||||
clean:
|
||||
-rm -f *.old *.$(SUF) mktables *.$(USUF) ack ack.1 $(ISRC)
|
||||
|
||||
ack: $(OBJ)
|
||||
$(CC) $(LDFLAGS) -o ack $(OBJ) $(MODDIR)/libstring.$(LIBSUF)
|
||||
|
||||
depend: $(ISRC)
|
||||
rm_deps Makefile > Makefile.new
|
||||
for i in $(CFILES) ; do \
|
||||
echo "`basename $$i .c`.$$(SUF): $$i" >> Makefile.new ; \
|
||||
echo ' $$(CC) -c $$(CFLAGS)' $$i >> Makefile.new ; \
|
||||
$(UTIL_HOME)/lib.bin/cpp -d $(INCLUDES) $$i | sed "s/^/`basename $$i .c`.$$(SUF): /" >> Makefile.new ; \
|
||||
done
|
||||
mv Makefile Makefile.old
|
||||
mv Makefile.new Makefile
|
||||
|
||||
dmach.c intable.c: mktables $(SRC_DIR)/dmach.h
|
||||
: mktables $(ACKDIR) # $(FE) $(INTABLES)
|
||||
mktables $(ACKDIR)
|
||||
|
||||
mktables: mktables.$(USUF)
|
||||
$(UCC) -o mktables $(ULDFLAGS) mktables.$(USUF)
|
||||
|
||||
mktables.$(USUF): $(SRC_DIR)/mktables.c
|
||||
$(UCC) -c $(UCFLAGS) $(SRC_DIR)/mktables.c
|
||||
|
||||
pr:
|
||||
@pr $(SRC_DIR)/proto.make $(HFILES) $(DSRC)
|
||||
|
||||
opr:
|
||||
make pr | opr
|
||||
|
||||
lint: $(ISRC)
|
||||
$(LINT) $(LINTFLAGS) $(CFILES) $(UTIL_HOME)/modules/lib/$(LINTPREF)string.$(LINTSUF)
|
||||
|
||||
# do not remove the next line
|
||||
#DEPENDENCIES
|
||||
list.$(SUF): $(SRC_DIR)/list.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/list.c
|
||||
list.$(SUF): $(SRC_DIR)/list.h
|
||||
list.$(SUF): $(SRC_DIR)/ack.h
|
||||
data.$(SUF): $(SRC_DIR)/data.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/data.c
|
||||
data.$(SUF): $(SRC_DIR)/data.h
|
||||
data.$(SUF): $(SRC_DIR)/trans.h
|
||||
data.$(SUF): $(SRC_DIR)/list.h
|
||||
data.$(SUF): $(SRC_DIR)/ack.h
|
||||
main.$(SUF): $(SRC_DIR)/main.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/main.c
|
||||
main.$(SUF): $(SRC_DIR)/data.h
|
||||
main.$(SUF): $(TARGET_HOME)/config/local.h
|
||||
main.$(SUF): $(SRC_DIR)/trans.h
|
||||
main.$(SUF): $(SRC_DIR)/list.h
|
||||
main.$(SUF): $(SRC_DIR)/ack.h
|
||||
scan.$(SUF): $(SRC_DIR)/scan.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/scan.c
|
||||
scan.$(SUF): $(SRC_DIR)/data.h
|
||||
scan.$(SUF): $(SRC_DIR)/trans.h
|
||||
scan.$(SUF): $(SRC_DIR)/list.h
|
||||
scan.$(SUF): $(SRC_DIR)/ack.h
|
||||
svars.$(SUF): $(SRC_DIR)/svars.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/svars.c
|
||||
svars.$(SUF): $(SRC_DIR)/ack.h
|
||||
trans.$(SUF): $(SRC_DIR)/trans.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/trans.c
|
||||
trans.$(SUF): $(SRC_DIR)/data.h
|
||||
trans.$(SUF): $(SRC_DIR)/grows.h
|
||||
trans.$(SUF): $(SRC_DIR)/trans.h
|
||||
trans.$(SUF): $(SRC_DIR)/list.h
|
||||
trans.$(SUF): $(SRC_DIR)/ack.h
|
||||
util.$(SUF): $(SRC_DIR)/util.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/util.c
|
||||
util.$(SUF): $(SRC_DIR)/ack.h
|
||||
rmach.$(SUF): $(SRC_DIR)/rmach.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/rmach.c
|
||||
rmach.$(SUF): $(SRC_DIR)/data.h
|
||||
rmach.$(SUF): $(SRC_DIR)/dmach.h
|
||||
rmach.$(SUF): $(SRC_DIR)/grows.h
|
||||
rmach.$(SUF): $(SRC_DIR)/trans.h
|
||||
rmach.$(SUF): $(SRC_DIR)/list.h
|
||||
rmach.$(SUF): $(TARGET_HOME)/config/em_path.h
|
||||
rmach.$(SUF): $(SRC_DIR)/ack.h
|
||||
run.$(SUF): $(SRC_DIR)/run.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/run.c
|
||||
run.$(SUF): $(SRC_DIR)/data.h
|
||||
run.$(SUF): $(SRC_DIR)/grows.h
|
||||
run.$(SUF): $(SRC_DIR)/trans.h
|
||||
run.$(SUF): $(SRC_DIR)/list.h
|
||||
run.$(SUF): $(SRC_DIR)/ack.h
|
||||
grows.$(SUF): $(SRC_DIR)/grows.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/grows.c
|
||||
grows.$(SUF): $(SRC_DIR)/grows.h
|
||||
grows.$(SUF): $(SRC_DIR)/ack.h
|
||||
files.$(SUF): $(SRC_DIR)/files.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/files.c
|
||||
files.$(SUF): $(TARGET_HOME)/config/em_path.h
|
||||
files.$(SUF): $(SRC_DIR)/data.h
|
||||
files.$(SUF): $(SRC_DIR)/grows.h
|
||||
files.$(SUF): $(SRC_DIR)/trans.h
|
||||
files.$(SUF): $(SRC_DIR)/list.h
|
||||
files.$(SUF): $(SRC_DIR)/ack.h
|
||||
dmach.$(SUF): dmach.c
|
||||
$(CC) -c $(CFLAGS) dmach.c
|
||||
dmach.$(SUF): $(SRC_DIR)/dmach.h
|
||||
intable.$(SUF): intable.c
|
||||
$(CC) -c $(CFLAGS) intable.c
|
||||
383
util/ack/rmach.c
383
util/ack/rmach.c
@@ -1,383 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ack.h"
|
||||
#include <em_path.h>
|
||||
#include "list.h"
|
||||
#include "trans.h"
|
||||
#include "grows.h"
|
||||
#include "dmach.h"
|
||||
#include "data.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
static char rcs_dmach[] = RCS_DMACH ;
|
||||
#endif
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* Read machine definitions and transformations */
|
||||
/* */
|
||||
/************************************************************************/
|
||||
|
||||
#define COMMENT '#'
|
||||
|
||||
#define VAR "var"
|
||||
#define PASS "name"
|
||||
#define IN "from"
|
||||
#define OUT "to"
|
||||
#define RES "outfile"
|
||||
#define PROG "program"
|
||||
#define MAPF "mapflag"
|
||||
#define ARGS "args"
|
||||
#define STD_IN "stdin"
|
||||
#define STD_OUT "stdout"
|
||||
#define PREP "prep"
|
||||
#define OPT "optimizer"
|
||||
#define LINKER "linker"
|
||||
#define COMBINER "combiner"
|
||||
#define PRIO "priority"
|
||||
#define RUNT "rts"
|
||||
#define NEEDT "need"
|
||||
#define CALL "callname"
|
||||
#define END "end"
|
||||
|
||||
extern growstring scanb();
|
||||
extern growstring scanvars();
|
||||
|
||||
int getline() ;
|
||||
int getinchar() ;
|
||||
static char *ty_name ;
|
||||
static char *bol ;
|
||||
|
||||
|
||||
static char *inname ;
|
||||
|
||||
setlist(name) char *name ; {
|
||||
/* Name is sought in the internal tables,
|
||||
if not present, the a file of that name is sought
|
||||
in first the current and then the EM Lib directory
|
||||
*/
|
||||
|
||||
inname=name ;
|
||||
open_in(name) ;
|
||||
while ( getline() ) {
|
||||
if ( strcmp(VAR,ty_name)==0 ) {
|
||||
doassign(bol,(char *)0,0) ;
|
||||
} else
|
||||
if ( strcmp(CALL,ty_name)==0 ) {
|
||||
if ( callname && strcmp(bol,callname)==0 ) {
|
||||
callname= (char *)0 ;
|
||||
#ifdef DEBUG
|
||||
if ( debug>=3 ) {
|
||||
vprint("found call name\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else
|
||||
if ( strcmp(PASS,ty_name)==0 ) {
|
||||
intrf() ;
|
||||
} else
|
||||
error("unknown keyword %s",ty_name) ;
|
||||
}
|
||||
close_in();
|
||||
#ifdef DEBUG
|
||||
if ( debug>=3 ) vprint("End %s\n",name) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int inoptlist(nm)
|
||||
char *nm ;
|
||||
{
|
||||
register char *p=Optlist ;
|
||||
|
||||
while ( p && *p ) {
|
||||
register char *q=nm ;
|
||||
|
||||
while ( *q!='\0' && *q++==*p ) p++ ;
|
||||
if ( *q=='\0' && ( *p=='\0' || *p==',' ) ) return 1 ;
|
||||
while ( *p!='\0' && *p++!=',' ) /* nothing */ ;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
intrf() {
|
||||
register trf *new ;
|
||||
growstring bline ;
|
||||
int twice ;
|
||||
int name_seen=0 ;
|
||||
|
||||
new= (trf *)getcore(sizeof *new) ;
|
||||
new->t_name= keeps(bol) ;
|
||||
for (;;) {
|
||||
if ( !getline() ) {
|
||||
fuerror("unexpected EOF on %s",inname) ;
|
||||
}
|
||||
twice= NO ;
|
||||
if ( strcmp(ty_name,IN)==0 ) {
|
||||
if ( new->t_in ) twice=YES ;
|
||||
new->t_in= keeps(bol);
|
||||
} else
|
||||
if ( strcmp(ty_name,OUT)==0 ) {
|
||||
if ( new->t_out ) twice=YES ;
|
||||
new->t_out= keeps(bol);
|
||||
} else
|
||||
if ( strcmp(ty_name,PROG)==0 ) {
|
||||
if ( new->t_prog ) twice=YES ;
|
||||
bline= scanb(bol); /* Scan for \ */
|
||||
new->t_prog= gr_final(&bline);
|
||||
} else
|
||||
if ( strcmp(ty_name,MAPF)==0 ) {
|
||||
/* First read the mapflags line
|
||||
and scan for backslashes */
|
||||
bline= scanb(bol) ;
|
||||
l_add(&new->t_mapf,gr_final(&bline)) ;
|
||||
} else
|
||||
if ( strcmp(ty_name,ARGS)==0 ) {
|
||||
if ( new->t_argd ) twice=YES ;
|
||||
bline= scanb(bol) ;
|
||||
new->t_argd= keeps(gr_start(bline)) ;
|
||||
gr_throw(&bline) ;
|
||||
} else
|
||||
if ( strcmp(ty_name,STD_IN)==0 ) {
|
||||
if ( new->t_stdin ) twice=YES ;
|
||||
new->t_stdin= YES ;
|
||||
} else
|
||||
if ( strcmp(ty_name,STD_OUT)==0 ) {
|
||||
if ( new->t_stdout ) twice=YES ;
|
||||
new->t_stdout= YES ;
|
||||
} else
|
||||
if ( strcmp(ty_name,PREP)==0 ) {
|
||||
if ( strcmp(bol,"always")==0 ) {
|
||||
if ( new->t_prep ) twice=YES ;
|
||||
new->t_prep=YES ;
|
||||
} else
|
||||
if ( strcmp(bol,"cond")==0 ) {
|
||||
if ( new->t_prep ) twice=YES ;
|
||||
new->t_prep=MAYBE ;
|
||||
} else
|
||||
if ( strcmp(bol,"is")==0 ) {
|
||||
if ( new->t_isprep ) twice=YES ;
|
||||
new->t_isprep= YES ;
|
||||
} else
|
||||
{
|
||||
fuerror("illegal preprocessor spec in %s: %s",
|
||||
inname,bol) ;
|
||||
}
|
||||
} else
|
||||
if ( strcmp(ty_name,OPT)==0 ) {
|
||||
if ( new->t_optim ) twice=YES ;
|
||||
new->t_optim= atoi(bol) ;
|
||||
if (new->t_optim <= 0) new->t_optim = 1;
|
||||
} else
|
||||
if ( strcmp(ty_name,LINKER)==0 ) {
|
||||
if ( new->t_linker ) twice=YES ;
|
||||
new->t_linker= YES ;
|
||||
new->t_combine= YES ;
|
||||
} else
|
||||
if ( strcmp(ty_name,COMBINER)==0 ) {
|
||||
if ( new->t_combine ) twice=YES ;
|
||||
new->t_combine= YES ;
|
||||
} else
|
||||
if ( strcmp(ty_name,PRIO)==0 ) {
|
||||
new->t_priority= atoi(bol) ;
|
||||
} else
|
||||
if ( strcmp(ty_name,RUNT)==0 ) {
|
||||
if ( new->t_rts ) twice=YES ;
|
||||
new->t_rts= keeps(bol) ;
|
||||
} else
|
||||
if ( strcmp(ty_name,NEEDT)==0 ) {
|
||||
if ( new->t_needed ) twice=YES ;
|
||||
new->t_needed= keeps(bol) ;
|
||||
} else
|
||||
if ( strcmp(ty_name,RES)==0 ) {
|
||||
if ( new->t_outfile ) twice=YES ;
|
||||
new->t_outfile= keeps(bol) ;
|
||||
} else
|
||||
if ( strcmp(ty_name,CALL)==0 ) {
|
||||
if ( callname && strcmp(bol,callname)==0 ) {
|
||||
name_seen=1 ;
|
||||
callname= (char *)0 ;
|
||||
#ifdef DEBUG
|
||||
if ( debug>=3 ) {
|
||||
vprint("found call name in %s\n",
|
||||
new->t_name) ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else
|
||||
if ( strcmp(ty_name,END)==0 ) {
|
||||
break ;
|
||||
} else {
|
||||
fuerror("illegal keyword %s %s",ty_name,bol);
|
||||
}
|
||||
if ( twice ) {
|
||||
werror("%s: specified twice for %s",
|
||||
ty_name, new->t_name) ;
|
||||
}
|
||||
}
|
||||
if ( ! ( new->t_name && new->t_out && new->t_prog ) ) {
|
||||
fuerror("insufficient specification for %s in %s",
|
||||
new->t_name,inname) ;
|
||||
}
|
||||
if ( ! new->t_argd ) new->t_argd="" ;
|
||||
/* Warning, side effect */
|
||||
if ( name_seen && new->t_rts ) {
|
||||
if ( rts && strcmp(rts,new->t_rts)!=0 ) {
|
||||
error("Attempt to use two run-time systems, %s and %s",
|
||||
rts, new->t_rts) ;
|
||||
}
|
||||
rts= new->t_rts ;
|
||||
keephead(rts) ; keeptail(rts) ;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if ( debug>=3 ) {
|
||||
register list_elem *elem ;
|
||||
vprint("%s: from %s to %s '%s'\n",
|
||||
new->t_name,new->t_in ? new->t_in : "(null)",new->t_out,new->t_prog) ;
|
||||
vprint("\targs: ") ; prns(new->t_argd) ;
|
||||
scanlist( l_first(new->t_mapf), elem ) {
|
||||
vprint("\t%s\n",l_content(*elem)) ;
|
||||
}
|
||||
if ( new->t_rts ) vprint("\trts: %s\n",new->t_rts) ;
|
||||
if ( new->t_needed ) vprint("\tneeded: %s\n",new->t_needed) ;
|
||||
}
|
||||
#endif
|
||||
if ( new->t_optim &&
|
||||
( new->t_optim <= Optlevel || inoptlist(new->t_name) ) ) {
|
||||
new->t_optim = Optlevel;
|
||||
}
|
||||
l_add(&tr_list,(char *)new) ;
|
||||
}
|
||||
|
||||
/************************** IO from core or file *******************/
|
||||
|
||||
static int incore ;
|
||||
static growstring rline ;
|
||||
static FILE *infile ;
|
||||
static char *inptr ;
|
||||
char *em_dir = EM_DIR;
|
||||
|
||||
open_in(name) register char *name ; {
|
||||
register dmach *cmac ;
|
||||
|
||||
gr_init(&rline) ;
|
||||
for ( cmac= massoc ; cmac->ma_index!= -1 ; cmac++ ) {
|
||||
if ( strcmp(name,cmac->ma_name)==0 ) {
|
||||
incore=YES ;
|
||||
inptr= &intable[cmac->ma_index] ;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
/* Not in core */
|
||||
incore= NO ;
|
||||
/* Try to read EM_DIR/lib/MACH/descr */
|
||||
gr_cat(&rline,em_dir) ;
|
||||
gr_cat(&rline,"/lib/") ; gr_cat(&rline,name) ;
|
||||
gr_cat(&rline,"/descr") ;
|
||||
infile= fopen(gr_start(rline),"r") ;
|
||||
if ( !infile ) {
|
||||
gr_throw(&rline) ;
|
||||
gr_cat(&rline,em_dir) ; gr_cat(&rline,"/") ;
|
||||
gr_cat(&rline,ACK_PATH); gr_cat(&rline,"/") ;
|
||||
gr_cat(&rline,name) ;
|
||||
infile= fopen(gr_start(rline),"r") ;
|
||||
}
|
||||
if ( !infile ) {
|
||||
infile= fopen(name,"r") ;
|
||||
}
|
||||
if ( infile==NULL ) {
|
||||
fuerror("Cannot find description for %s",name) ;
|
||||
}
|
||||
}
|
||||
|
||||
close_in() {
|
||||
if ( !incore ) fclose(infile) ;
|
||||
gr_throw(&rline) ;
|
||||
}
|
||||
|
||||
char *readline() {
|
||||
/* Get a line from the input,
|
||||
return 0 if at end,
|
||||
The line is stored in a volatile buffer,
|
||||
a pointer to the line is returned.
|
||||
*/
|
||||
register int nchar ;
|
||||
enum { BOL, ESCAPE, SKIPPING, MOL } state = BOL ;
|
||||
|
||||
gr_throw(&rline) ;
|
||||
for (;;) {
|
||||
nchar= getinchar() ;
|
||||
if ( nchar==EOF ) {
|
||||
if ( state!=BOL ) {
|
||||
werror("incomplete line in %s", inname) ;
|
||||
}
|
||||
return 0 ;
|
||||
}
|
||||
if ( state==SKIPPING ) {
|
||||
if ( nchar=='\n' ) {
|
||||
state= MOL ;
|
||||
} else {
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
if ( state==ESCAPE ) {
|
||||
switch( nchar ) {
|
||||
case '\n' :
|
||||
break ;
|
||||
default :
|
||||
gr_add(&rline,BSLASH) ;
|
||||
case COMMENT :
|
||||
case BSLASH :
|
||||
gr_add(&rline,nchar) ;
|
||||
break ;
|
||||
}
|
||||
state= MOL ;
|
||||
continue ;
|
||||
}
|
||||
switch ( nchar ) {
|
||||
case '\n' : gr_add(&rline,0) ;
|
||||
return gr_start(rline) ;
|
||||
case COMMENT : state= SKIPPING ;
|
||||
break ;
|
||||
case BSLASH : state= ESCAPE ;
|
||||
break ;
|
||||
default : gr_add(&rline,nchar) ;
|
||||
state= MOL ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int getinchar() {
|
||||
register int token ;
|
||||
|
||||
if ( incore ) {
|
||||
if ( *inptr==0 ) return EOF ;
|
||||
return *inptr++ ;
|
||||
}
|
||||
token= getc(infile) ;
|
||||
if ( (token>=0177 || token <=0 ) && token !=EOF ) {
|
||||
fuerror("Non-ascii character in description file %s",inname);
|
||||
}
|
||||
return token ;
|
||||
}
|
||||
|
||||
int getline() {
|
||||
register char *c_ptr ;
|
||||
|
||||
do {
|
||||
if ( (c_ptr=readline())==(char *)0 ) return 0 ;
|
||||
ty_name= skipblank(c_ptr) ;
|
||||
} while ( *ty_name==0 ) ;
|
||||
c_ptr= firstblank(ty_name) ;
|
||||
if ( *c_ptr ) {
|
||||
*c_ptr++ =0 ;
|
||||
c_ptr= skipblank(c_ptr) ;
|
||||
}
|
||||
bol= c_ptr ;
|
||||
return 1 ;
|
||||
}
|
||||
150
util/ack/run.c
150
util/ack/run.c
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ack.h"
|
||||
#include "list.h"
|
||||
#include "trans.h"
|
||||
#include "grows.h"
|
||||
#include "data.h"
|
||||
#include <signal.h>
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
#define ARG_MORE 40 /* The size of args chunks to allocate */
|
||||
|
||||
extern growstring scanvars();
|
||||
|
||||
static char **arglist ; /* The first argument */
|
||||
static unsigned argcount ; /* The current number of arguments */
|
||||
static unsigned argmax; /* The maximum number of arguments so far */
|
||||
|
||||
int runphase(phase) register trf *phase ; {
|
||||
register list_elem *elem ;
|
||||
char *prog ; int result ;
|
||||
growstring bline ;
|
||||
|
||||
bline=scanvars(phase->t_prog) ;
|
||||
prog=gr_final(&bline) ;
|
||||
if ( v_flag || debug ) {
|
||||
if ( v_flag==1 && !debug ) {
|
||||
vprint("%s",phase->t_name) ;
|
||||
if ( !phase->t_combine ) {
|
||||
vprint(" %s%s\n",p_basename,
|
||||
strrindex(in.p_path,SUFCHAR) ) ;
|
||||
} else {
|
||||
scanlist(l_first(phase->t_inputs), elem) {
|
||||
vprint(" %s",p_cont(*elem)->p_path);
|
||||
}
|
||||
vprint("\n") ;
|
||||
}
|
||||
} else {
|
||||
/* list all args */
|
||||
vprint("%s",prog) ;
|
||||
scanlist(l_first(phase->t_flags), elem) {
|
||||
vprint(" %s",l_content(*elem)) ;
|
||||
}
|
||||
scanlist(l_first(phase->t_args), elem) {
|
||||
vprint(" %s",l_content(*elem)) ;
|
||||
}
|
||||
vprint("\n") ;
|
||||
}
|
||||
}
|
||||
argcount=0 ;
|
||||
x_arg(phase->t_name) ;
|
||||
scanlist(l_first(phase->t_flags), elem) {
|
||||
x_arg(l_content(*elem)) ;
|
||||
}
|
||||
scanlist(l_first(phase->t_args), elem) {
|
||||
x_arg(l_content(*elem)) ;
|
||||
}
|
||||
x_arg( (char *)0 ) ;
|
||||
result=run_exec(phase,prog) ;
|
||||
throws(prog) ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
int run_exec(phase,prog) trf *phase ; char *prog ; {
|
||||
int status, child, waitchild ;
|
||||
|
||||
do_flush();
|
||||
while ( (child=fork())== -1 ) ;
|
||||
if ( child ) {
|
||||
/* The parent */
|
||||
do {
|
||||
waitchild= wait(&status) ;
|
||||
if ( waitchild== -1 ) {
|
||||
fatal("missing child") ;
|
||||
}
|
||||
} while ( waitchild!=child) ;
|
||||
if ( status ) {
|
||||
if ( status&0200 && (status&0177)!=SIGQUIT &&
|
||||
t_flag<=1 ) unlink("core") ;
|
||||
switch ( status&0177 ) {
|
||||
case 0 :
|
||||
break ;
|
||||
case SIGHUP:
|
||||
case SIGINT:
|
||||
case SIGQUIT:
|
||||
case SIGTERM:
|
||||
quit(-5) ;
|
||||
default:
|
||||
error("%s died with signal %d",
|
||||
prog,status&0177) ;
|
||||
}
|
||||
/* The assumption is that processes voluntarely
|
||||
dying with a non-zero status already produced
|
||||
some sort of error message to the outside world.
|
||||
*/
|
||||
n_error++ ;
|
||||
return 0 ;
|
||||
}
|
||||
return 1 ; /* From the parent */
|
||||
}
|
||||
/* The child */
|
||||
if ( phase->t_stdin ) {
|
||||
if ( !in.p_path ) {
|
||||
fatal("no input file for %s",phase->t_name) ;
|
||||
}
|
||||
close(0) ;
|
||||
if ( open(in.p_path,0)!=0 ) {
|
||||
error("cannot open %s",in.p_path) ;
|
||||
exit(1) ;
|
||||
}
|
||||
}
|
||||
if ( phase->t_stdout ) {
|
||||
if ( !out.p_path ) {
|
||||
fatal("no output file for %s",phase->t_name) ;
|
||||
}
|
||||
close(1) ;
|
||||
if ( creat(out.p_path,0666)!=1 ) {
|
||||
close(1); dup(2);
|
||||
error("cannot create %s",out.p_path) ;
|
||||
exit(1) ;
|
||||
}
|
||||
}
|
||||
execv(prog,arglist) ;
|
||||
if ( phase->t_stdout ) { close(1) ; dup(2) ; }
|
||||
error("Cannot execute %s",prog) ;
|
||||
exit(1) ;
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
x_arg(string) char *string ; {
|
||||
/* Add one execute argument to the argument vector */
|
||||
if ( argcount==argmax ) {
|
||||
if ( argmax==0 ) {
|
||||
argmax= 2*ARG_MORE ;
|
||||
arglist= (char **)getcore(argmax*sizeof (char *)) ;
|
||||
} else {
|
||||
argmax += ARG_MORE ;
|
||||
arglist= (char **)changecore((char *)arglist,
|
||||
argmax*sizeof (char *)) ;
|
||||
}
|
||||
}
|
||||
*(arglist+argcount++) = string ;
|
||||
}
|
||||
255
util/ack/scan.c
255
util/ack/scan.c
@@ -1,255 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ack.h"
|
||||
#include "list.h"
|
||||
#include "trans.h"
|
||||
#include "data.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
enum f_path getpath(first) register trf **first ; {
|
||||
/* Try to find a transformation path */
|
||||
|
||||
start_scan();
|
||||
/*
|
||||
The end result is the chaining of
|
||||
the consequtive phases with the t_next field.
|
||||
The list is scanned for possible transformations
|
||||
stopping at stopsuffix or the last transformation in the list.
|
||||
The scan flags are set by this process.
|
||||
When a transformation is found, it is compared with
|
||||
the last transformation found.
|
||||
*/
|
||||
try(l_first(tr_list),p_suffix);
|
||||
return scan_end(first);
|
||||
}
|
||||
|
||||
/******************** data used only while scanning *******************/
|
||||
|
||||
static int last_pcount; /* The added priority of
|
||||
the best path so far */
|
||||
|
||||
static int last_ncount; /* The # of non-optimizing transformations
|
||||
in the best path sofar */
|
||||
|
||||
static int last_ocount; /* The # of optimizing transformations in the
|
||||
best path sofar */
|
||||
|
||||
static int suf_found; /* Was the suffix at least recognized ? */
|
||||
|
||||
/******************** The hard work ********************/
|
||||
|
||||
start_scan() {
|
||||
register list_elem *scan ;
|
||||
|
||||
scanlist(l_first(tr_list),scan) {
|
||||
t_cont(*scan)->t_scan=NO ;
|
||||
}
|
||||
suf_found= 0 ;
|
||||
#ifdef DEBUG
|
||||
if ( debug>=3 ) vprint("Scan_start\n");
|
||||
#endif
|
||||
last_ncount= -1 ;
|
||||
last_ocount= 0 ;
|
||||
}
|
||||
|
||||
try(f_scan,suffix) list_elem *f_scan; char *suffix; {
|
||||
register list_elem *scan ;
|
||||
register trf *trafo ;
|
||||
/* Try to find a transformation path starting at f_scan for a
|
||||
file with the indicated suffix.
|
||||
If the suffix is already reached or a combiner is found
|
||||
call scan_found() to OK the scan.
|
||||
If a transformation is found it calls itself recursively
|
||||
with as starting point the next transformation in the list.
|
||||
*/
|
||||
if ( stopsuffix && *stopsuffix && strcmp(stopsuffix,suffix)==0 ) {
|
||||
scan_found();
|
||||
return ;
|
||||
}
|
||||
if (! f_scan) return;
|
||||
scanlist(f_scan, scan) {
|
||||
trafo= t_cont(*scan) ;
|
||||
if ( satisfy(trafo,suffix) ) {
|
||||
/* Found a transformation */
|
||||
suf_found= 1;
|
||||
#ifdef DEBUG
|
||||
if ( debug>=4 ) {
|
||||
vprint("Found %s for %s: result %s\n",
|
||||
trafo->t_name,suffix,trafo->t_out);
|
||||
}
|
||||
#endif
|
||||
trafo->t_scan=YES ;
|
||||
if ( trafo->t_prep ) {
|
||||
if ( !cpp_trafo ) {
|
||||
find_cpp() ;
|
||||
}
|
||||
if ( stopsuffix &&
|
||||
strcmp(stopsuffix,
|
||||
cpp_trafo->t_out)==0 )
|
||||
{
|
||||
scan_found() ;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
if ( trafo->t_next ) {
|
||||
/* We know what happens from this phase on,
|
||||
so take a shortcut.
|
||||
*/
|
||||
register trf *sneak ;
|
||||
sneak= trafo ;
|
||||
while( sneak=sneak->t_next ) {
|
||||
sneak->t_scan=YES ;
|
||||
}
|
||||
scan_found() ;
|
||||
sneak= trafo ;
|
||||
while( sneak=sneak->t_next ) {
|
||||
sneak->t_scan=NO ;
|
||||
}
|
||||
return ;
|
||||
}
|
||||
if ( trafo->t_linker && stopsuffix && !*stopsuffix ) {
|
||||
trafo->t_scan=NO ;
|
||||
scan_found() ;
|
||||
return ;
|
||||
}
|
||||
if (! l_next(*scan) && !stopsuffix) {
|
||||
scan_found() ;
|
||||
} else {
|
||||
try(l_next(*scan),trafo->t_out);
|
||||
}
|
||||
trafo->t_scan= NO ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scan_found() {
|
||||
register list_elem *scan;
|
||||
int ncount, ocount, pcount ;
|
||||
|
||||
suf_found= 1;
|
||||
#ifdef DEBUG
|
||||
if ( debug>=3 ) vprint("Scan found\n") ;
|
||||
#endif
|
||||
/* Gather data used in comparison */
|
||||
ncount=0; ocount=0; pcount=0;
|
||||
scanlist(l_first(tr_list),scan) {
|
||||
if (t_cont(*scan)->t_scan) {
|
||||
#ifdef DEBUG
|
||||
if ( debug>=4 ) vprint("%s-",t_cont(*scan)->t_name) ;
|
||||
#endif
|
||||
if( t_cont(*scan)->t_optim ) ocount++ ;else ncount++ ;
|
||||
if( t_cont(*scan)->t_optim>Optlevel ) pcount-- ;
|
||||
pcount += t_cont(*scan)->t_priority ;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if ( debug>=4 ) vprint("\n");
|
||||
#endif
|
||||
/* Is this transformation better then any found yet ? */
|
||||
#ifdef DEBUG
|
||||
if ( debug>=3 ) {
|
||||
vprint("old n:%d, o:%d, p:%d - new n:%d, o:%d, p:%d\n",
|
||||
last_ncount,last_ocount,last_pcount,
|
||||
ncount,ocount,pcount) ;
|
||||
}
|
||||
#endif
|
||||
if ( last_ncount== -1 || /* None found yet */
|
||||
last_pcount<pcount || /* Better priority */
|
||||
( last_pcount==pcount && /* Same prio, and */
|
||||
( last_ncount>ncount || /* Shorter nec. path */
|
||||
(last_ncount==ncount && /* Same nec. path, optimize?*/
|
||||
(Optlevel? last_ocount<ocount : last_ocount>ocount ))))) {
|
||||
/* Yes it is */
|
||||
#ifdef DEBUG
|
||||
if ( debug>=3 ) vprint("Better\n");
|
||||
#endif
|
||||
scanlist(l_first(tr_list),scan) {
|
||||
t_cont(*scan)->t_bscan=t_cont(*scan)->t_scan;
|
||||
}
|
||||
last_ncount=ncount; last_ocount=ocount; last_pcount=pcount;
|
||||
}
|
||||
}
|
||||
|
||||
int satisfy(trafo,suffix) register trf *trafo; char *suffix ; {
|
||||
register char *f_char, *l_char ;
|
||||
/* Check whether this transformation is present for
|
||||
the current machine and the parameter suffix is among
|
||||
the input suffices. If so, return 1. 0 otherwise
|
||||
*/
|
||||
if ( trafo->t_isprep ) return 0 ;
|
||||
l_char=trafo->t_in ;
|
||||
while ( l_char ) {
|
||||
f_char= l_char ;
|
||||
if ( *f_char!=SUFCHAR || ! *(f_char+1) ) {
|
||||
fuerror("Illegal input suffix entry for %s",
|
||||
trafo->t_name) ;
|
||||
}
|
||||
l_char=strindex(f_char+1,SUFCHAR);
|
||||
if ( l_char ) *l_char = 0;
|
||||
if ( strcmp(f_char,suffix)==0 ) {
|
||||
if ( l_char ) *l_char = SUFCHAR;
|
||||
return 1;
|
||||
}
|
||||
if ( l_char ) *l_char = SUFCHAR;
|
||||
}
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
enum f_path scan_end(first) trf **first ; { /* Finalization */
|
||||
/* Return value indicating whether a transformation was found */
|
||||
/* Set the flags for the transformation up to, but not including,
|
||||
the combiner
|
||||
*/
|
||||
register trf *prev, *curr ;
|
||||
register list_elem *scan;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( debug>=3 ) vprint("End_scan\n");
|
||||
#endif
|
||||
if ( last_ncount== -1 ) return suf_found ? F_NOPATH : F_NOMATCH ;
|
||||
#ifdef DEBUG
|
||||
if ( debug>=2 ) vprint("Transformation found\n");
|
||||
#endif
|
||||
prev= (trf *)0 ; *first= prev ;
|
||||
scanlist(l_first(tr_list),scan) {
|
||||
curr= t_cont(*scan) ;
|
||||
if ( curr->t_bscan ) {
|
||||
if ( prev ) {
|
||||
prev->t_next= curr ;
|
||||
if ( curr->t_linker ) prev->t_keep=YES ;
|
||||
} else {
|
||||
*first= curr ;
|
||||
}
|
||||
if ( curr->t_next ) {
|
||||
return F_OK ;
|
||||
}
|
||||
prev=curr ;
|
||||
}
|
||||
}
|
||||
if ( cpp_trafo && stopsuffix &&
|
||||
strcmp(stopsuffix,cpp_trafo->t_out)==0 ) {
|
||||
cpp_trafo->t_keep=YES ;
|
||||
}
|
||||
if ( prev ) {
|
||||
prev->t_keep=YES ;
|
||||
}
|
||||
return F_OK ;
|
||||
}
|
||||
|
||||
find_cpp() {
|
||||
register list_elem *elem ;
|
||||
scanlist( l_first(tr_list), elem ) {
|
||||
if ( t_cont(*elem)->t_isprep ) {
|
||||
if ( cpp_trafo ) fuerror("Multiple cpp's present") ;
|
||||
cpp_trafo= t_cont(*elem) ;
|
||||
}
|
||||
}
|
||||
if ( !cpp_trafo ) fuerror("No cpp present") ;
|
||||
}
|
||||
118
util/ack/svars.c
118
util/ack/svars.c
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ack.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
/* The processing of string valued variables,
|
||||
this is an almost self contained module.
|
||||
|
||||
Five externally visible routines:
|
||||
|
||||
setsvar(name,result)
|
||||
Associate the name with the result.
|
||||
|
||||
name a string pointer
|
||||
result a string pointer
|
||||
|
||||
setpvar(name,routine)
|
||||
Associate the name with the routine.
|
||||
|
||||
name a string pointer
|
||||
routine a routine id
|
||||
|
||||
The parameters name and result are supposed to be pointing to
|
||||
non-volatile string storage used only for this call.
|
||||
|
||||
char *getvar(name)
|
||||
returns the pointer to a string associated with name,
|
||||
the pointer is produced by returning result or the
|
||||
value returned by calling the routine.
|
||||
|
||||
name a string pointer
|
||||
|
||||
Other routines called
|
||||
|
||||
fatal(args*) When something goes wrong
|
||||
getcore(size) Core allocation
|
||||
|
||||
*/
|
||||
|
||||
extern char *getcore();
|
||||
extern fatal();
|
||||
|
||||
struct vars {
|
||||
char *v_name;
|
||||
enum { routine, string } v_type;
|
||||
|
||||
union {
|
||||
char *v_string;
|
||||
char *(*v_routine)();
|
||||
} v_value ;
|
||||
struct vars *v_next ;
|
||||
};
|
||||
|
||||
static struct vars *v_first ;
|
||||
|
||||
static struct vars *newvar(name) char *name; {
|
||||
register struct vars *new ;
|
||||
|
||||
for ( new=v_first ; new ; new= new->v_next ) {
|
||||
if ( strcmp(name,new->v_name)==0 ) {
|
||||
throws(name) ;
|
||||
if ( new->v_type== string ) {
|
||||
throws(new->v_value.v_string) ;
|
||||
}
|
||||
return new ;
|
||||
}
|
||||
}
|
||||
new= (struct vars *)getcore( (unsigned)sizeof (struct vars));
|
||||
new->v_name= name ;
|
||||
new->v_next= v_first ;
|
||||
v_first= new ;
|
||||
return new ;
|
||||
}
|
||||
|
||||
setsvar(name,str) char *name, *str ; {
|
||||
register struct vars *new ;
|
||||
|
||||
new= newvar(name);
|
||||
#ifdef DEBUG
|
||||
if ( debug>=2 ) vprint("%s=%s\n", name, str) ;
|
||||
#endif
|
||||
new->v_type= string;
|
||||
new->v_value.v_string= str;
|
||||
}
|
||||
|
||||
setpvar(name,rout) char *name, *(*rout)() ; {
|
||||
register struct vars *new ;
|
||||
|
||||
new= newvar(name);
|
||||
#ifdef DEBUG
|
||||
if ( debug>=2 ) vprint("%s= (*%o)()\n",name,rout) ;
|
||||
#endif
|
||||
new->v_type= routine;
|
||||
new->v_value.v_routine= rout;
|
||||
}
|
||||
|
||||
char *getvar(name) char *name ; {
|
||||
register struct vars *scan ;
|
||||
|
||||
for ( scan=v_first ; scan ; scan= scan->v_next ) {
|
||||
if ( strcmp(name,scan->v_name)==0 ) {
|
||||
switch ( scan->v_type ) {
|
||||
case string:
|
||||
return scan->v_value.v_string ;
|
||||
case routine:
|
||||
return (*scan->v_value.v_routine)() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (char *)0 ;
|
||||
}
|
||||
666
util/ack/trans.c
666
util/ack/trans.c
@@ -1,666 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ack.h"
|
||||
#include "list.h"
|
||||
#include "trans.h"
|
||||
#include "grows.h"
|
||||
#include "data.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
static char rcs_trans[] = RCS_TRANS ;
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
/* Routines for transforming from one file type to another */
|
||||
/****************************************************************************/
|
||||
|
||||
static growstring head ;
|
||||
static int touch_head= NO ;
|
||||
static growstring tail ;
|
||||
static int touch_tail= NO ;
|
||||
|
||||
char *headvar(),*tailvar() ;
|
||||
|
||||
int transform(phase) register trf *phase ; {
|
||||
int ok ;
|
||||
|
||||
if ( !setfiles(phase) ) {
|
||||
disc_files(phase) ;
|
||||
return 0 ;
|
||||
}
|
||||
getcallargs(phase) ;
|
||||
ok= runphase(phase) ;
|
||||
if ( !ok ) rmfile(&out) ;
|
||||
/* Free the space occupied by the arguments,
|
||||
except for the linker, since we are bound to exit soon
|
||||
and do not foresee further need of memory space */
|
||||
if ( !phase->t_linker ) discardargs(phase) ;
|
||||
disc_files(phase) ;
|
||||
return ok ;
|
||||
}
|
||||
|
||||
getmapflags(phase) register trf *phase ; {
|
||||
register path *l_in ;
|
||||
register list_elem *elem ;
|
||||
int scanned ;
|
||||
register char *ptr ;
|
||||
|
||||
scanlist(l_first(flags),elem) {
|
||||
scanned= *(l_content(*elem))&NO_SCAN ;
|
||||
*(l_content(*elem)) &= ~NO_SCAN ;
|
||||
if ( mapflag(&(phase->t_mapf),l_content(*elem)) ) {
|
||||
scanned=NO_SCAN ;
|
||||
#ifdef DEBUG
|
||||
if ( debug >=4 ) {
|
||||
vprint("phase %s, added mapflag for %s\n",
|
||||
phase->t_name,
|
||||
l_content(*elem) ) ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
*(l_content(*elem)) |= scanned ;
|
||||
}
|
||||
if ( phase->t_linker ) {
|
||||
scanlist(l_first(phase->t_inputs),elem) {
|
||||
l_in = p_cont(*elem) ;
|
||||
if ( mapflag(&(phase->t_mapf),l_in->p_path) ) {
|
||||
ptr= keeps(getvar(LIBVAR)) ;
|
||||
clr_noscan(ptr) ;
|
||||
#ifdef DEBUG
|
||||
if ( debug >=4 ) {
|
||||
vprint("phase %s, library %s(%s)\n",
|
||||
phase->t_name,l_in->p_path,ptr) ;
|
||||
}
|
||||
#endif
|
||||
if ( l_in->p_keeps) throws(l_in->p_path) ;
|
||||
l_in->p_path= ptr ;
|
||||
l_in->p_keeps=YES ;
|
||||
}
|
||||
}
|
||||
scanlist(l_first(flags),elem) {
|
||||
/* Get the flags remaining for the loader,
|
||||
That is: all the flags neither eaten by ack nor
|
||||
one of the subprograms called so-far.
|
||||
The last fact is indicated by the NO_SCAN bit
|
||||
in the first character of the flag.
|
||||
*/
|
||||
if ( !( *(l_content(*elem))&NO_SCAN ) ) {
|
||||
l_add(&(phase->t_flags),l_content(*elem)) ;
|
||||
#ifdef DEBUG
|
||||
if ( debug >=4 ) {
|
||||
vprint("phase %s, added flag %s\n",
|
||||
phase->t_name,
|
||||
l_content(*elem) ) ;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
do_Rflag(argp) char *argp ; {
|
||||
l_add(&R_list,argp) ;
|
||||
}
|
||||
|
||||
char *headvar() {
|
||||
if ( !touch_head) return "" ;
|
||||
return gr_start(head) ;
|
||||
}
|
||||
|
||||
add_head(str) char *str; {
|
||||
if ( !touch_head) {
|
||||
gr_init(&head) ;
|
||||
touch_head=YES ;
|
||||
}
|
||||
gr_cat(&head,str) ;
|
||||
}
|
||||
|
||||
char *tailvar() {
|
||||
if ( !touch_tail ) return "" ;
|
||||
return gr_start(tail) ;
|
||||
}
|
||||
|
||||
add_tail(str) char *str ; {
|
||||
if ( !touch_tail ) {
|
||||
gr_init(&tail) ;
|
||||
touch_tail=YES ;
|
||||
}
|
||||
gr_cat(&tail,str) ;
|
||||
}
|
||||
|
||||
|
||||
transini() {
|
||||
register list_elem *elem ;
|
||||
register trf *phase ;
|
||||
|
||||
scanlist(l_first(tr_list), elem) {
|
||||
phase = t_cont(*elem) ;
|
||||
if ( !phase->t_linker ) getmapflags(phase);
|
||||
}
|
||||
scanlist(l_first(R_list), elem) {
|
||||
set_Rflag(l_content(*elem)) ;
|
||||
}
|
||||
l_clear(&R_list) ;
|
||||
setpvar(keeps(HEAD),headvar) ;
|
||||
setpvar(keeps(TAIL),tailvar) ;
|
||||
}
|
||||
|
||||
set_Rflag(argp) register char *argp ; {
|
||||
register char *eos ;
|
||||
register list_elem *prog ;
|
||||
register int length ;
|
||||
char *eq, *colon ;
|
||||
|
||||
eos= strindex(&argp[2],'-');
|
||||
eq= strindex(&argp[2],EQUAL) ;
|
||||
colon= strindex(&argp[2],':');
|
||||
if ( !eos ) {
|
||||
eos= eq ;
|
||||
} else {
|
||||
if ( eq && eq<eos ) eos= eq ;
|
||||
}
|
||||
if ( colon && ( !eos || eos>colon ) ) eos= colon ;
|
||||
if ( !eos ) {
|
||||
if ( !(argp[0]&NO_SCAN) ) werror("Incorrect use of -R flag") ;
|
||||
return ;
|
||||
}
|
||||
length= eos - &argp[2] ;
|
||||
scanlist(l_first(tr_list), prog) {
|
||||
if ( strncmp(t_cont(*prog)->t_name, &argp[2], length )==0 &&
|
||||
t_cont(*prog)->t_name[length]==0 /* Same name length */) {
|
||||
if ( *eos=='-' ) {
|
||||
if ( !(argp[0]&NO_SCAN) ) {
|
||||
/* If not already taken by a mapflag */
|
||||
l_add(&(t_cont(*prog)->t_flags),eos) ;
|
||||
}
|
||||
} else
|
||||
if ( *eos=='=' ) {
|
||||
t_cont(*prog)->t_prog= eos+1 ;
|
||||
} else {
|
||||
t_cont(*prog)->t_priority= atoi(eos+1) ;
|
||||
}
|
||||
argp[0] |= NO_SCAN ;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
if ( !(argp[0]&NO_SCAN) ) werror("Cannot find program for %s",argp) ;
|
||||
return ;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/* */
|
||||
/* The creation of arguments for exec for a transformation */
|
||||
/* */
|
||||
/**************************************************************************/
|
||||
|
||||
growstring scanb(line) char *line ; {
|
||||
/* Scan a line for backslashes, setting the NO_SCAN bit in characters
|
||||
preceded by a backslash.
|
||||
*/
|
||||
register char *in_c ;
|
||||
register int token ;
|
||||
growstring result ;
|
||||
enum { TEXT, ESCAPED } state = TEXT ;
|
||||
|
||||
gr_init(&result) ;
|
||||
for ( in_c= line ; *in_c ; in_c++ ) {
|
||||
token= *in_c&0377 ;
|
||||
switch( state ) {
|
||||
case TEXT :
|
||||
if ( token==BSLASH ) {
|
||||
state= ESCAPED ;
|
||||
} else {
|
||||
gr_add(&result,token) ;
|
||||
}
|
||||
break ;
|
||||
case ESCAPED :
|
||||
gr_add(&result,token|NO_SCAN) ;
|
||||
state=TEXT ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
gr_add(&result,0) ;
|
||||
if ( state!=TEXT ) werror("flag line ends with %c",BSLASH) ;
|
||||
return result ;
|
||||
}
|
||||
|
||||
growstring scanvars(line) char *line ; {
|
||||
/* Scan a line variable replacements started by S_VAR.
|
||||
Two sequences exist: S_VAR name E_VAR, S_VAR name A_VAR text E_VAR.
|
||||
neither name nor text may contain further replacements.
|
||||
In the first form an error message is issued if the name is not
|
||||
present in the variables, the second form produces text
|
||||
in that case.
|
||||
The sequence S_VAR S_VAR is transformed into S_VAR.
|
||||
This to allow later recognition in mapflags, where B_SLASH
|
||||
would be preventing any recognition.
|
||||
*/
|
||||
register char *in_c ;
|
||||
register int token ;
|
||||
growstring result ;
|
||||
growstring name ;
|
||||
register char *tr ;
|
||||
enum { TEXT, FIRST, NAME, SKIP, COPY } state = TEXT ;
|
||||
|
||||
gr_init(&result) ; gr_init(&name) ;
|
||||
for ( in_c= line ; *in_c ; in_c++ ) {
|
||||
token= *in_c&0377 ;
|
||||
switch( state ) {
|
||||
case TEXT :
|
||||
if ( token==S_VAR ) {
|
||||
state= FIRST ;
|
||||
} else {
|
||||
gr_add(&result,token) ;
|
||||
}
|
||||
break ;
|
||||
case FIRST :
|
||||
switch ( token ) {
|
||||
case S_VAR :
|
||||
state= TEXT ;
|
||||
gr_add(&result,token) ;
|
||||
break ;
|
||||
case A_VAR :
|
||||
case C_VAR :
|
||||
fatal("empty string variable name") ;
|
||||
default :
|
||||
state=NAME ;
|
||||
gr_add(&name,token) ;
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
case NAME:
|
||||
switch ( token ) {
|
||||
case A_VAR :
|
||||
gr_add(&name,0) ;
|
||||
if ( tr=getvar(gr_start(name)) ) {
|
||||
while ( *tr ) {
|
||||
gr_add(&result,*tr++) ;
|
||||
}
|
||||
state=SKIP ;
|
||||
} else {
|
||||
state=COPY ;
|
||||
}
|
||||
gr_throw(&name) ;
|
||||
break ;
|
||||
case C_VAR :
|
||||
gr_add(&name,0) ;
|
||||
if ( tr=getvar(gr_start(name)) ) {
|
||||
while ( *tr ) {
|
||||
gr_add(&result,*tr++);
|
||||
}
|
||||
} else {
|
||||
werror("No definition for %s",
|
||||
gr_start(name)) ;
|
||||
}
|
||||
state=TEXT ;
|
||||
gr_throw(&name) ;
|
||||
break ;
|
||||
default:
|
||||
gr_add(&name,token) ;
|
||||
break ;
|
||||
}
|
||||
break ;
|
||||
case SKIP :
|
||||
if ( token==C_VAR ) state= TEXT ;
|
||||
break ;
|
||||
case COPY :
|
||||
if ( token==C_VAR ) state= TEXT ; else {
|
||||
gr_add(&result,token) ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
}
|
||||
gr_add(&result,0) ;
|
||||
if ( state!=TEXT ) {
|
||||
werror("flag line misses %c",C_VAR) ;
|
||||
gr_throw(&name) ;
|
||||
}
|
||||
return result ;
|
||||
}
|
||||
|
||||
growstring scanexpr(line) char *line ; {
|
||||
/* Scan a line for conditional or flag expressions,
|
||||
dependent on the type. The format is
|
||||
S_EXPR suflist M_EXPR suflist T_EXPR tail C_EXPR
|
||||
the head and tail are passed to treat, together with the
|
||||
growstring for futher treatment.
|
||||
Nesting is not allowed.
|
||||
*/
|
||||
register char *in_c ;
|
||||
char *heads ;
|
||||
register int token ;
|
||||
growstring sufs, tailval ;
|
||||
growstring result ;
|
||||
static list_head fsuff, lsuff ;
|
||||
enum { TEXT, FDOT, FSUF, LDOT, LSUF, FTAIL } state = TEXT ;
|
||||
|
||||
gr_init(&result) ; gr_init(&sufs) ; gr_init(&tailval) ;
|
||||
for ( in_c= line ; *in_c ; in_c++ ) {
|
||||
token= *in_c&0377 ;
|
||||
switch( state ) {
|
||||
case TEXT :
|
||||
if ( token==S_EXPR ) {
|
||||
state= FDOT ;
|
||||
heads=in_c ;
|
||||
} else gr_add(&result,token) ;
|
||||
break ;
|
||||
case FDOT :
|
||||
if ( token==M_EXPR ) {
|
||||
state=LDOT ;
|
||||
break ;
|
||||
}
|
||||
token &= ~NO_SCAN ;
|
||||
if ( token!=SUFCHAR ) {
|
||||
error("Missing %c in expression",SUFCHAR) ;
|
||||
}
|
||||
gr_add(&sufs,token) ; state=FSUF ;
|
||||
break ;
|
||||
case FSUF :
|
||||
if ( token==M_EXPR || (token&~NO_SCAN)==SUFCHAR) {
|
||||
gr_add(&sufs,0) ;
|
||||
l_add(&fsuff,gr_final(&sufs)) ;
|
||||
}
|
||||
if ( token==M_EXPR ) {
|
||||
state=LDOT ;
|
||||
} else gr_add(&sufs,token&~NO_SCAN) ;
|
||||
break ;
|
||||
case LDOT :
|
||||
if ( token==T_EXPR ) {
|
||||
state=FTAIL ;
|
||||
break ;
|
||||
}
|
||||
token &= ~NO_SCAN ;
|
||||
if ( token!=SUFCHAR ) {
|
||||
error("Missing %c in expression",SUFCHAR) ;
|
||||
}
|
||||
gr_add(&sufs,token) ; state=LSUF ;
|
||||
break ;
|
||||
case LSUF :
|
||||
if ( token==T_EXPR || (token&~NO_SCAN)==SUFCHAR) {
|
||||
gr_add(&sufs,0) ;
|
||||
l_add(&lsuff,gr_final(&sufs)) ;
|
||||
}
|
||||
if ( token==T_EXPR ) {
|
||||
state=FTAIL ;
|
||||
} else gr_add(&sufs,token&~NO_SCAN) ;
|
||||
break ;
|
||||
case FTAIL :
|
||||
if ( token==C_EXPR ) {
|
||||
/* Found one !! */
|
||||
gr_add(&tailval,0) ;
|
||||
condit(&result,&fsuff,&lsuff,gr_start(tailval)) ;
|
||||
l_throw(&fsuff) ; l_throw(&lsuff) ;
|
||||
gr_throw(&tailval) ;
|
||||
state=TEXT ;
|
||||
} else gr_add(&tailval,token) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
gr_add(&result,0) ;
|
||||
if ( state!=TEXT ) {
|
||||
l_throw(&fsuff) ; l_throw(&lsuff) ; gr_throw(&tailval) ;
|
||||
werror("flag line has unclosed expression starting with %6s",
|
||||
heads) ;
|
||||
}
|
||||
return result ;
|
||||
}
|
||||
|
||||
condit(line,fsuff,lsuff,tailval) growstring *line ;
|
||||
list_head *fsuff, *lsuff;
|
||||
char *tailval ;
|
||||
{
|
||||
register list_elem *first ;
|
||||
register list_elem *last ;
|
||||
|
||||
#ifdef DEBUG
|
||||
if ( debug>=4 ) vprint("Conditional for %s, ",tailval) ;
|
||||
#endif
|
||||
scanlist( l_first(*fsuff), first ) {
|
||||
scanlist( l_first(*lsuff), last ) {
|
||||
if ( strcmp(l_content(*first),l_content(*last))==0 ) {
|
||||
/* Found */
|
||||
#ifdef DEBUG
|
||||
if ( debug>=4 ) vprint(" matched\n") ;
|
||||
#endif
|
||||
while ( *tailval) gr_add(line,*tailval++ ) ;
|
||||
return ;
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if ( debug>=4) vprint(" non-matched\n") ;
|
||||
#endif
|
||||
}
|
||||
|
||||
int mapflag(maplist,cflag) list_head *maplist ; char *cflag ; {
|
||||
/* Expand a flag expression */
|
||||
/* The flag "cflag" is checked for each of the mapflags.
|
||||
A mapflag entry has the form
|
||||
-text NAME=replacement or -text*text NAME=replacement
|
||||
The star matches anything as in the shell.
|
||||
If the entry matches the assignment will take place
|
||||
This replacement is subjected to argument matching only.
|
||||
When a match took place the replacement is returned
|
||||
when not, (char *)0.
|
||||
The replacement sits in stable storage.
|
||||
*/
|
||||
register list_elem *elem ;
|
||||
|
||||
scanlist(l_first(*maplist),elem) {
|
||||
if ( mapexpand(l_content(*elem),cflag) ) {
|
||||
return 1 ;
|
||||
}
|
||||
}
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
int mapexpand(mapentry,cflag)
|
||||
char *mapentry, *cflag ;
|
||||
{
|
||||
register char *star ;
|
||||
register char *ptr ;
|
||||
register char *space ;
|
||||
int length ;
|
||||
|
||||
star=strindex(mapentry,STAR) ;
|
||||
space=firstblank(mapentry) ;
|
||||
if ( star >space ) star= (char *)0 ;
|
||||
if ( star ) {
|
||||
length= space-star-1 ;
|
||||
if ( strncmp(mapentry,cflag,star-mapentry) ||
|
||||
strncmp(star+1,cflag+strlen(cflag)-length,length) ) {
|
||||
return 0 ;
|
||||
}
|
||||
/* Match */
|
||||
/* Now set star to the first char of the star
|
||||
replacement and length to its length
|
||||
*/
|
||||
length=strlen(cflag)-(star-mapentry)-length ;
|
||||
if ( length<0 ) return 0 ;
|
||||
star=cflag+(star-mapentry) ;
|
||||
#ifdef DEBUG
|
||||
if ( debug>=6 ) {
|
||||
vprint("Starmatch (%s,%s) %.*s\n",
|
||||
mapentry,cflag,length,star) ;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if ( strncmp(mapentry,cflag,space-mapentry)!=0 ||
|
||||
cflag[space-mapentry] ) {
|
||||
return 0 ;
|
||||
}
|
||||
}
|
||||
ptr= skipblank(space) ;
|
||||
if ( *ptr==0 ) return 1 ;
|
||||
doassign(ptr,star,length) ;
|
||||
return 1 ;
|
||||
}
|
||||
|
||||
doassign(line,star,length) char *line, *star ; {
|
||||
growstring varval, name, temp ;
|
||||
register char *ptr ;
|
||||
|
||||
gr_init(&varval) ;
|
||||
gr_init(&name) ;
|
||||
ptr= line ;
|
||||
for ( ; *ptr && *ptr!=SPACE && *ptr!=TAB && *ptr!=EQUAL ; ptr++ ) {
|
||||
gr_add(&name,*ptr) ;
|
||||
}
|
||||
ptr= strindex(ptr,EQUAL) ;
|
||||
if ( !ptr ) {
|
||||
error("Missing %c in assignment %s",EQUAL,line);
|
||||
return ;
|
||||
}
|
||||
temp= scanvars(ptr+1) ;
|
||||
for ( ptr=gr_start(temp); *ptr; ptr++ ) switch ( *ptr ) {
|
||||
case STAR :
|
||||
if ( star ) {
|
||||
while ( length-- ) gr_add(&varval,*star++|NO_SCAN) ;
|
||||
break ;
|
||||
}
|
||||
default :
|
||||
gr_add(&varval,*ptr) ;
|
||||
break ;
|
||||
}
|
||||
gr_throw(&temp) ;
|
||||
gr_add(&name,0) ; gr_add(&varval,0) ;
|
||||
setsvar(gr_final(&name),gr_final(&varval)) ;
|
||||
}
|
||||
|
||||
#define ISBLANK(c) ( (c)==SPACE || (c)==TAB )
|
||||
|
||||
unravel(line,action) char *line ; int (*action)() ; {
|
||||
/* Unravel the line, get arguments a la shell */
|
||||
/* each argument is handled to action */
|
||||
/* The input string is left intact */
|
||||
register char *in_c ;
|
||||
register int token ;
|
||||
enum { BLANK, ARG } state = BLANK ;
|
||||
growstring argum ;
|
||||
|
||||
in_c=line ;
|
||||
for (;;) {
|
||||
token= *in_c&0377 ;
|
||||
switch ( state ) {
|
||||
case BLANK :
|
||||
if ( token==0 ) break ;
|
||||
if ( !ISBLANK(token) ) {
|
||||
state= ARG ;
|
||||
gr_init(&argum) ;
|
||||
gr_add(&argum,token&~NO_SCAN) ;
|
||||
}
|
||||
break ;
|
||||
case ARG :
|
||||
if ( ISBLANK(token) || token==0 ) {
|
||||
gr_add(&argum,0) ;
|
||||
(*action)(gr_start(argum)) ;
|
||||
gr_throw(&argum) ;
|
||||
state=BLANK ;
|
||||
} else {
|
||||
gr_add(&argum,token&~NO_SCAN) ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
if ( token == 0 ) break ;
|
||||
in_c++ ;
|
||||
}
|
||||
}
|
||||
|
||||
char *c_rep(string,place,rep) char *string, *place, *rep ; {
|
||||
/* Produce a string in stable storage produced from 'string'
|
||||
with the character at place replaced by rep
|
||||
*/
|
||||
growstring name ;
|
||||
register char *nc ;
|
||||
register char *xc ;
|
||||
|
||||
gr_init(&name) ;
|
||||
for ( nc=string ; *nc && nc<place ; nc++ ) {
|
||||
gr_add(&name,*nc) ;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if ( *nc==0 ) fatal("Place is not in string") ;
|
||||
#endif
|
||||
for ( xc=rep ; *xc ; xc++ ) gr_add(&name,*xc|NO_SCAN) ;
|
||||
gr_add(&name,0) ;
|
||||
gr_cat(&name,nc+1) ;
|
||||
return gr_final(&name) ;
|
||||
}
|
||||
|
||||
static list_head *curargs ;
|
||||
static list_head *comb_args ;
|
||||
|
||||
addargs(string) char *string ; {
|
||||
register char *temp, *repc ;
|
||||
register list_elem *elem ;
|
||||
|
||||
repc=strindex(string,C_IN) ;
|
||||
if ( repc ) {
|
||||
/* INPUT FILE TOKEN seen, replace it and scan further */
|
||||
if ( repc==string && string[1]==0 ) {
|
||||
if ( in.p_path ) { /* All but combiner */
|
||||
l_add(curargs,keeps(in.p_path)) ;
|
||||
} else {
|
||||
scanlist( l_first(*comb_args), elem ) {
|
||||
l_add(curargs,
|
||||
keeps(p_cont(*elem)->p_path)) ;
|
||||
}
|
||||
}
|
||||
return ;
|
||||
}
|
||||
if ( in.p_path ) { /* Not for the combiners */
|
||||
temp=c_rep(string,repc,in.p_path) ;
|
||||
addargs(temp) ;
|
||||
throws(temp) ;
|
||||
} else { /* For the combiners */
|
||||
scanlist( l_first(*comb_args), elem ) {
|
||||
temp=c_rep(string,repc,p_cont(*elem)->p_path);
|
||||
addargs(temp) ;
|
||||
throws(temp) ;
|
||||
}
|
||||
}
|
||||
return ;
|
||||
}
|
||||
repc=strindex(string,C_OUT) ;
|
||||
if ( repc ) {
|
||||
/* replace the outfile token as with the infile token */
|
||||
#ifdef DEBUG
|
||||
if ( !out.p_path ) fatal("missing output filename") ;
|
||||
#endif
|
||||
temp=c_rep(string,repc,out.p_path) ;
|
||||
addargs(temp) ;
|
||||
throws(temp) ;
|
||||
return ;
|
||||
}
|
||||
temp= keeps(string) ;
|
||||
clr_noscan(temp) ;
|
||||
l_add(curargs,temp) ;
|
||||
}
|
||||
|
||||
getcallargs(phase) register trf *phase ; {
|
||||
growstring arg1, arg2 ;
|
||||
|
||||
arg1= scanvars(phase->t_argd) ;
|
||||
#ifdef DEBUG
|
||||
if ( debug>=3 ) { vprint("\tvars: ") ; prns(gr_start(arg1)) ; }
|
||||
#endif
|
||||
arg2= scanexpr(gr_start(arg1)) ;
|
||||
#ifdef DEBUG
|
||||
if ( debug>=3 ) { vprint("\texpr: ") ; prns(gr_start(arg2)) ; }
|
||||
#endif
|
||||
gr_throw(&arg1) ;
|
||||
curargs= &phase->t_args ;
|
||||
if (phase->t_combine) comb_args = &phase->t_inputs ;
|
||||
unravel( gr_start(arg2), addargs ) ;
|
||||
gr_throw(&arg2) ;
|
||||
}
|
||||
|
||||
discardargs(phase) register trf *phase ; {
|
||||
l_throw(&phase->t_args) ;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#ifndef NORCSID
|
||||
#define RCS_TRANS "$Id$"
|
||||
#endif
|
||||
|
||||
/* This structure is the center of all actions */
|
||||
/* It contains the description of all phases,
|
||||
the suffices they consume and produce and various properties */
|
||||
|
||||
typedef struct transform trf;
|
||||
|
||||
struct transform {
|
||||
char *t_in ; /* Suffices in '.o.k' */
|
||||
char *t_out ; /* Result '.suffix' */
|
||||
char *t_outfile ; /* Resulting output file */
|
||||
char *t_name ; /* The name of this transformation */
|
||||
list_head t_mapf ; /* Mapflags argument, uses varrep */
|
||||
char *t_argd ; /* Argument descriptor, uses varrep */
|
||||
char *t_needed ; /* Suffix indicating the libraries needed */
|
||||
char *t_rts ; /* Suffix indicating the major language used*/
|
||||
int t_stdin:1 ; /* The input is taken on stdin */
|
||||
int t_stdout:1 ; /* The output comes on stdout */
|
||||
int t_combine:1 ; /* Transform several files to one result */
|
||||
int t_visited:1 ; /* NO before setup, YES after */
|
||||
int t_prep:2 ; /* Needs preprocessor YES/NO/MAYBE */
|
||||
int t_isprep:1 ; /* Is preprocessor */
|
||||
int t_keep:1 ; /* Keep the output file */
|
||||
int t_scan:1 ; /* Used while finding path's */
|
||||
int t_bscan:1 ; /* Best scan so far, while finding path's */
|
||||
int t_linker:1 ; /* The linker usurps all unrecognized flags */
|
||||
int t_do:1 ; /* Is in a path to execute */
|
||||
int t_blocked:1 ; /* An input file could not be produced */
|
||||
short t_optim ; /* Is optimizer, + optimizer level */
|
||||
short t_priority ; /* Importance of including phase in scan */
|
||||
list_head t_inputs ; /* The input 'path's of a combiner */
|
||||
char *t_origname ; /* The basename of the output file */
|
||||
trf *t_next ; /* The transformation to be executed next */
|
||||
char *t_prog ; /* Pathname for load file */
|
||||
list_head t_flags ; /* List of flags */
|
||||
list_head t_args ; /* List of arguments */
|
||||
} ;
|
||||
|
||||
#define t_cont(elem) ((trf *)l_content(elem))
|
||||
184
util/ack/util.c
184
util/ack/util.c
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
/**********************************************************************/
|
||||
/* */
|
||||
/* Several utility routines used throughout ack */
|
||||
/* error handling, string handling and such. */
|
||||
/* */
|
||||
/**********************************************************************/
|
||||
|
||||
#include "ack.h"
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
extern char *progname ;
|
||||
extern int w_flag ;
|
||||
extern int n_error;
|
||||
|
||||
extern char *calloc();
|
||||
extern char *realloc();
|
||||
|
||||
#ifdef DEBUG
|
||||
# define STDOUT stdout
|
||||
#else
|
||||
# define STDOUT stderr
|
||||
#endif
|
||||
|
||||
char *basename(string) char *string ; {
|
||||
static char retval[256] ;
|
||||
char *last_dot, *last_start ;
|
||||
register char *store;
|
||||
register char *fetch ;
|
||||
register int ctoken ;
|
||||
|
||||
last_dot= (char *)0 ;
|
||||
last_start= string ;
|
||||
for ( fetch=string ; ; fetch++ ) {
|
||||
switch ( ctoken= *fetch&0377 ) {
|
||||
case SUFCHAR : last_dot=fetch ; break ;
|
||||
case '/' : last_start=fetch+1 ; break ;
|
||||
case 0 : goto out ;
|
||||
}
|
||||
if ( !isascii(ctoken) || !isprint(ctoken) ) {
|
||||
werror("non-ascii characters in argument %s",string) ;
|
||||
}
|
||||
}
|
||||
out:
|
||||
if ( ! *last_start ) fuerror("empty filename \"%s\"",string) ;
|
||||
for ( fetch= last_start, store=retval ;
|
||||
*fetch && fetch!=last_dot && store< &retval[sizeof retval-1] ;
|
||||
fetch++, store++ ) {
|
||||
*store= *fetch ;
|
||||
}
|
||||
*store= 0 ;
|
||||
return retval ;
|
||||
}
|
||||
|
||||
clr_noscan(str) char *str ; {
|
||||
register char *ptr ;
|
||||
for ( ptr=str ; *ptr ; ptr++ ) {
|
||||
*ptr&= ~NO_SCAN ;
|
||||
}
|
||||
}
|
||||
|
||||
char *skipblank(str) char *str ; {
|
||||
register char *ptr ;
|
||||
|
||||
for ( ptr=str ; *ptr==SPACE || *ptr==TAB ; ptr++ ) ;
|
||||
return ptr ;
|
||||
}
|
||||
|
||||
char *firstblank(str) char *str ; {
|
||||
register char *ptr ;
|
||||
|
||||
for ( ptr=str ; *ptr && *ptr!=SPACE && *ptr!=TAB ; ptr++ ) ;
|
||||
return ptr ;
|
||||
}
|
||||
|
||||
/* VARARGS1 */
|
||||
fatal(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
|
||||
/* Fatal internal error */
|
||||
fprintf(STDOUT,"%s: fatal internal error, ",progname) ;
|
||||
fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
|
||||
fprintf(STDOUT,"\n") ;
|
||||
quit(-2) ;
|
||||
}
|
||||
|
||||
|
||||
/* VARARGS1 */
|
||||
vprint(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
|
||||
/* Diagnostic print, no auto NL */
|
||||
fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
prns(s) register char *s ; {
|
||||
for ( ; *s ; s++ ) {
|
||||
putc((*s&0377)&~NO_SCAN,STDOUT) ;
|
||||
}
|
||||
putc('\n',STDOUT) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* VARARGS1 */
|
||||
fuerror(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
|
||||
/* Fatal user error */
|
||||
fprintf(STDOUT,"%s: ",progname) ;
|
||||
fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
|
||||
fprintf(STDOUT,"\n") ;
|
||||
quit(-1) ;
|
||||
}
|
||||
|
||||
/* VARARGS1 */
|
||||
werror(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
|
||||
/* Warning user error, w_flag */
|
||||
if ( w_flag ) return ;
|
||||
fprintf(STDOUT,"%s: warning, ",progname) ;
|
||||
fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
|
||||
fprintf(STDOUT,"\n") ;
|
||||
}
|
||||
|
||||
/* VARARGS1 */
|
||||
error(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
|
||||
/* User error, it is the callers responsibility to quit */
|
||||
fprintf(STDOUT,"%s: ",progname) ;
|
||||
fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
|
||||
fprintf(STDOUT,"\n") ;
|
||||
n_error++ ;
|
||||
}
|
||||
|
||||
do_flush() {
|
||||
fflush(stdout) ;
|
||||
fflush(stderr) ;
|
||||
}
|
||||
|
||||
void
|
||||
noodstop() {
|
||||
quit(-3) ;
|
||||
}
|
||||
|
||||
quit(code) {
|
||||
rmtemps();
|
||||
exit(code);
|
||||
}
|
||||
/******
|
||||
char *keeps(string)
|
||||
Keep the string in stable storage.
|
||||
throws(string)
|
||||
Remove the string stored by keep from stable storage.
|
||||
***********/
|
||||
|
||||
char *keeps(str) char *str ; {
|
||||
register char *result ;
|
||||
result= getcore( (unsigned)(strlen(str)+1) ) ;
|
||||
if ( !result ) fatal("Out of core") ;
|
||||
return strcpy(result,str) ;
|
||||
}
|
||||
|
||||
throws(str) char *str ; {
|
||||
freecore(str) ;
|
||||
}
|
||||
|
||||
char *getcore(size) unsigned size ; {
|
||||
register char *retptr ;
|
||||
|
||||
retptr= calloc(1,size) ;
|
||||
if ( !retptr ) fatal("Out of memory") ;
|
||||
return retptr ;
|
||||
}
|
||||
|
||||
char *changecore(ptr,size) char *ptr ; unsigned size ; {
|
||||
register char *retptr ;
|
||||
|
||||
retptr= realloc(ptr,size) ;
|
||||
if ( !retptr ) fatal("Out of memory") ;
|
||||
return retptr ;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
proto.make
|
||||
anm.c
|
||||
asize.c
|
||||
astrip.c
|
||||
ashow.c
|
||||
anm.1
|
||||
asize.1
|
||||
astrip.1
|
||||
@@ -1,39 +0,0 @@
|
||||
EM = ../..
|
||||
BINDIR = $(EM)/bin
|
||||
MANDIR = $(EM)/man
|
||||
LIBDIR = $(EM)/modules/lib
|
||||
h = $(EM)/h
|
||||
LDFLAGS =
|
||||
CFLAGS = $(LDFLAGS) -O -I$h
|
||||
ALL = anm asize astrip
|
||||
OFILES = anm.o asize.o astrip.o
|
||||
CFILES = anm.c asize.c astrip.c
|
||||
LIBS = $(LIBDIR)/libobject.a
|
||||
|
||||
all: $(ALL)
|
||||
|
||||
anm: anm.c
|
||||
$(CC) $(CFLAGS) -o anm anm.c $(LIBS)
|
||||
asize: asize.c
|
||||
$(CC) $(CFLAGS) -o asize asize.c $(LIBS)
|
||||
astrip: astrip.c
|
||||
$(CC) $(CFLAGS) -o astrip astrip.c $(LIBS)
|
||||
#not installed:
|
||||
ashow: ashow.c
|
||||
$(CC) $(CFLAGS) -o ashow ashow.c $(LIBS)
|
||||
|
||||
install: all
|
||||
for i in $(ALL); do rm -f $(BINDIR)/$$i; cp $$i $(BINDIR)/$$i; done
|
||||
for i in anm.1 asize.1 astrip.1; do rm -f $(MANDIR)/$$i; cp $$i $(MANDIR)/$$i; done
|
||||
|
||||
cmp: all
|
||||
-for i in $(ALL); do cmp $$i $(BINDIR)/$$i; done
|
||||
-for i in anm.1 astrip.1 asize.1 ; do cmp $$i $(MANDIR)/$$i; done
|
||||
|
||||
clean: ; rm -f $(ALL) $(OFILES)
|
||||
|
||||
pr:
|
||||
@pr `pwd`/Makefile `pwd`/anm.c `pwd`/astrip.c `pwd`/asize.c
|
||||
|
||||
opr:
|
||||
make pr | opr
|
||||
@@ -1,74 +0,0 @@
|
||||
.TH ANM 1 "$Revision$"
|
||||
.SH NAME
|
||||
anm \- print name list
|
||||
.SH SYNOPSIS
|
||||
anm [ \-gnoprus ] [ file ... ]
|
||||
.SH DESCRIPTION
|
||||
.I Anm
|
||||
prints the name list (symbol table) of each ack.out(5) format object
|
||||
.I file
|
||||
in the argument list. If an argument is an aal(1) or arch(1) archive,
|
||||
a listing of each object file in the archive will be produced.
|
||||
If no
|
||||
.I file
|
||||
is given, the symbols in
|
||||
`a.out'
|
||||
are listed.
|
||||
.PP
|
||||
Each symbol name is preceded by its value, a section indicator
|
||||
and a type indicator.
|
||||
A section indicator can be
|
||||
.SM
|
||||
.B U
|
||||
(undefined symbol),
|
||||
.SM
|
||||
.B A
|
||||
(absolute symbol),
|
||||
.SM
|
||||
.B C
|
||||
(common symbol), a section number (section related symbol),
|
||||
or
|
||||
.SM
|
||||
.B -
|
||||
(other symbol).
|
||||
A type indicator can be
|
||||
.SM
|
||||
.B F
|
||||
(filename),
|
||||
.SM
|
||||
.B M
|
||||
(module name),
|
||||
.SM
|
||||
.B E
|
||||
(external (global) symbol),
|
||||
or
|
||||
.SM
|
||||
.B -
|
||||
(local symbol).
|
||||
The output is sorted alphabetically.
|
||||
.PP
|
||||
Options are:
|
||||
.TP
|
||||
.B \-g
|
||||
Print only external (global) symbols.
|
||||
.TP
|
||||
.B \-n
|
||||
Sort numerically rather than alphabetically.
|
||||
.TP
|
||||
.B \-o
|
||||
Prepend file name to each output line rather than only once.
|
||||
.TP
|
||||
.B \-p
|
||||
Don't sort; print in symbol-table order.
|
||||
.TP
|
||||
.B \-r
|
||||
Sort in reverse order.
|
||||
.TP
|
||||
.B \-u
|
||||
Print only undefined symbols.
|
||||
.TP
|
||||
.B \-s
|
||||
Sort in section order.
|
||||
.sh FILES
|
||||
.SH SEE ALSO
|
||||
ack.out(5)
|
||||
339
util/amisc/anm.c
339
util/amisc/anm.c
@@ -1,339 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Id$ */
|
||||
/*
|
||||
** print symbol tables for
|
||||
** ACK object files
|
||||
**
|
||||
** anm [-gopruns] [name ...]
|
||||
*/
|
||||
|
||||
#include "out.h"
|
||||
#include "arch.h"
|
||||
#include "ranlib.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
int numsort_flg;
|
||||
int sectsort_flg;
|
||||
int undef_flg;
|
||||
int revsort_flg = 1;
|
||||
int globl_flg;
|
||||
int nosort_flg;
|
||||
int arch_flg;
|
||||
int prep_flg;
|
||||
int read_error;
|
||||
struct outhead hbuf;
|
||||
struct outsect sbuf;
|
||||
long off;
|
||||
char *malloc();
|
||||
char *realloc();
|
||||
long s_base[S_MAX]; /* for specially encoded bases */
|
||||
char *filename;
|
||||
int narg;
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
|
||||
if (--argc>0 && argv[1][0]=='-' && argv[1][1]!=0) {
|
||||
argv++;
|
||||
while (*++*argv) switch (**argv) {
|
||||
case 'n': /* sort numerically */
|
||||
numsort_flg++;
|
||||
continue;
|
||||
|
||||
case 's': /* sort in section order */
|
||||
sectsort_flg++;
|
||||
continue;
|
||||
|
||||
case 'g': /* globl symbols only */
|
||||
globl_flg++;
|
||||
continue;
|
||||
|
||||
case 'u': /* undefined symbols only */
|
||||
undef_flg++;
|
||||
continue;
|
||||
|
||||
case 'r': /* sort in reverse order */
|
||||
revsort_flg = -1;
|
||||
continue;
|
||||
|
||||
case 'p': /* don't sort -- symbol table order */
|
||||
nosort_flg++;
|
||||
continue;
|
||||
|
||||
case 'o': /* prepend a name to each line */
|
||||
prep_flg++;
|
||||
continue;
|
||||
|
||||
default: /* oops */
|
||||
fprintf(stderr, "anm: invalid argument -%c\n", *argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
argc--;
|
||||
}
|
||||
if (argc == 0) {
|
||||
argc = 1;
|
||||
argv[1] = "a.out";
|
||||
}
|
||||
narg = argc;
|
||||
|
||||
while(argc--) {
|
||||
int fd;
|
||||
|
||||
filename = *++argv;
|
||||
if ((fd = open(filename, 0)) < 0) {
|
||||
fprintf(stderr, "anm: cannot open %s\n", filename);
|
||||
continue;
|
||||
}
|
||||
process(fd);
|
||||
close(fd);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
extern int rd_unsigned2();
|
||||
extern long lseek();
|
||||
extern char *strncpy();
|
||||
|
||||
process(fd)
|
||||
int fd;
|
||||
{
|
||||
unsigned int magic;
|
||||
long nextpos;
|
||||
struct ar_hdr archive_header;
|
||||
static char buf[sizeof(archive_header.ar_name)+1];
|
||||
|
||||
if (narg > 1) printf("\n%s:\n", filename);
|
||||
|
||||
magic = rd_unsigned2(fd);
|
||||
switch(magic) {
|
||||
case O_MAGIC:
|
||||
lseek(fd, 0L, 0);
|
||||
do_file(fd);
|
||||
break;
|
||||
case ARMAG:
|
||||
case AALMAG:
|
||||
while (rd_arhdr(fd, &archive_header)) {
|
||||
nextpos = lseek(fd, 0L, 1) + archive_header.ar_size;
|
||||
if (nextpos & 1) nextpos++;
|
||||
strncpy(buf,archive_header.ar_name,sizeof(archive_header.ar_name));
|
||||
filename = buf;
|
||||
if ( strcmp(filename, SYMDEF)) {
|
||||
printf("\n%s:\n", filename);
|
||||
do_file(fd);
|
||||
}
|
||||
lseek(fd, nextpos, 0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "anm: %s -- bad format\n", filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
do_file(fd)
|
||||
int fd;
|
||||
{
|
||||
struct outname *nbufp = NULL;
|
||||
struct outname nbuf;
|
||||
char *cbufp;
|
||||
long fi_to_co;
|
||||
long n;
|
||||
unsigned readcount;
|
||||
int i,j;
|
||||
int compare();
|
||||
|
||||
read_error = 0;
|
||||
rd_fdopen(fd);
|
||||
|
||||
rd_ohead(&hbuf);
|
||||
if (read_error) {
|
||||
return;
|
||||
}
|
||||
if (BADMAGIC(hbuf)) {
|
||||
return;
|
||||
}
|
||||
|
||||
n = hbuf.oh_nname;
|
||||
if (n == 0) {
|
||||
fprintf(stderr, "anm: %s -- no name list\n", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
if (hbuf.oh_nchar == 0) {
|
||||
fprintf(stderr, "anm: %s -- no names\n", filename);
|
||||
return;
|
||||
}
|
||||
if ((readcount = hbuf.oh_nchar) != hbuf.oh_nchar) {
|
||||
fprintf(stderr, "anm: string area too big in %s\n", filename);
|
||||
exit(2);
|
||||
}
|
||||
|
||||
/* store special section bases ??? */
|
||||
if (hbuf.oh_flags & HF_8086) {
|
||||
rd_sect(&sbuf, hbuf.oh_nsect);
|
||||
if (read_error) {
|
||||
return;
|
||||
}
|
||||
for (i=0; i<hbuf.oh_nsect; i++) {
|
||||
s_base[i+S_MIN] =
|
||||
(sbuf.os_base>>12) & 03777760;
|
||||
}
|
||||
}
|
||||
|
||||
if ((cbufp = (char *)malloc(readcount)) == NULL) {
|
||||
fprintf(stderr, "anm: out of memory on %s\n", filename);
|
||||
exit(2);
|
||||
}
|
||||
rd_string(cbufp, hbuf.oh_nchar);
|
||||
if (read_error) {
|
||||
free(cbufp);
|
||||
return;
|
||||
}
|
||||
|
||||
fi_to_co = (long) (cbufp - OFF_CHAR(hbuf));
|
||||
i = 0;
|
||||
while (--n >= 0) {
|
||||
rd_name(&nbuf, 1);
|
||||
if (read_error) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (globl_flg && (nbuf.on_type&S_EXT)==0)
|
||||
continue;
|
||||
|
||||
if (undef_flg
|
||||
&&
|
||||
((nbuf.on_type&S_TYP)!=S_UND || (nbuf.on_type&S_ETC)!=0))
|
||||
continue;
|
||||
|
||||
if (nbuf.on_foff == 0) nbuf.on_mptr = 0;
|
||||
else nbuf.on_mptr = (char *) (nbuf.on_foff + fi_to_co);
|
||||
|
||||
/* adjust value for specially encoded bases */
|
||||
if (hbuf.oh_flags & HF_8086) {
|
||||
if (((nbuf.on_type&S_ETC) == 0) ||
|
||||
((nbuf.on_type&S_ETC) == S_SCT)) {
|
||||
j = nbuf.on_type&S_TYP;
|
||||
if ((j>=S_MIN) && (j<=S_MAX))
|
||||
nbuf.on_valu += s_base[j];
|
||||
}
|
||||
}
|
||||
|
||||
if (nbufp == NULL)
|
||||
nbufp = (struct outname *)malloc(sizeof(struct outname));
|
||||
else
|
||||
nbufp = (struct outname *)realloc(nbufp, (i+1)*sizeof(struct outname));
|
||||
if (nbufp == NULL) {
|
||||
fprintf(stderr, "anm: out of memory on %s\n", filename);
|
||||
exit(2);
|
||||
}
|
||||
nbufp[i++] = nbuf;
|
||||
}
|
||||
|
||||
if (nbufp && nosort_flg==0)
|
||||
qsort(nbufp, i, sizeof(struct outname), compare);
|
||||
|
||||
for (n=0; n<i; n++) {
|
||||
char cs1[4];
|
||||
char cs2[4];
|
||||
|
||||
if (prep_flg)
|
||||
printf("%s:", filename);
|
||||
|
||||
switch(nbufp[n].on_type&S_ETC) {
|
||||
case S_SCT:
|
||||
sprintf(cs1, "%2d", (nbufp[n].on_type&S_TYP) - S_MIN);
|
||||
sprintf(cs2, " S");
|
||||
break;
|
||||
case S_FIL:
|
||||
sprintf(cs1, " -");
|
||||
sprintf(cs2, " F");
|
||||
break;
|
||||
case S_MOD:
|
||||
sprintf(cs1, " -");
|
||||
sprintf(cs2, " M");
|
||||
break;
|
||||
case S_COM:
|
||||
sprintf(cs1, " C");
|
||||
if (nbufp[n].on_type&S_EXT)
|
||||
sprintf(cs2, " E");
|
||||
else
|
||||
sprintf(cs2, " -");
|
||||
break;
|
||||
case 0:
|
||||
if (nbufp[n].on_type&S_EXT)
|
||||
sprintf(cs2, " E");
|
||||
else
|
||||
sprintf(cs2, " -");
|
||||
|
||||
switch(nbufp[n].on_type&S_TYP) {
|
||||
case S_UND:
|
||||
sprintf(cs1, " U");
|
||||
break;
|
||||
case S_ABS:
|
||||
sprintf(cs1, " A");
|
||||
break;
|
||||
default:
|
||||
sprintf(cs1, "%2d", (nbufp[n].on_type&S_TYP) - S_MIN);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sprintf(cs1, "??");
|
||||
sprintf(cs2, " ?");
|
||||
}
|
||||
|
||||
printf("%8lx %s %s %s\n",nbufp[n].on_valu,cs1,cs2,nbufp[n].on_mptr ? nbufp[n].on_mptr : "(NULL)");
|
||||
}
|
||||
|
||||
if (nbufp)
|
||||
free((char *)nbufp);
|
||||
if (cbufp)
|
||||
free((char *)cbufp);
|
||||
}
|
||||
|
||||
compare(p1, p2)
|
||||
struct outname *p1, *p2;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (sectsort_flg) {
|
||||
if ((p1->on_type&S_TYP) > (p2->on_type&S_TYP))
|
||||
return(revsort_flg);
|
||||
if ((p1->on_type&S_TYP) < (p2->on_type&S_TYP))
|
||||
return(-revsort_flg);
|
||||
}
|
||||
|
||||
if (numsort_flg) {
|
||||
if (p1->on_valu > p2->on_valu)
|
||||
return(revsort_flg);
|
||||
if (p1->on_valu < p2->on_valu)
|
||||
return(-revsort_flg);
|
||||
}
|
||||
|
||||
if (! p1->on_mptr) {
|
||||
if (! p2->on_mptr) return 0;
|
||||
return -revsort_flg;
|
||||
}
|
||||
if (! p2->on_mptr) return revsort_flg;
|
||||
|
||||
i = strcmp(p1->on_mptr, p2->on_mptr);
|
||||
|
||||
if (i > 0)
|
||||
return(revsort_flg);
|
||||
if (i < 0)
|
||||
return(-revsort_flg);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
rd_fatal()
|
||||
{
|
||||
fprintf(stderr,"read error on %s\n", filename);
|
||||
read_error = 1;
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
static char rcsid[] = "$Id$";
|
||||
/*
|
||||
* show - make the contents of an ACK object file human readable.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <out.h>
|
||||
|
||||
#define OK 0 /* Return value of gethead if Orl Korekt. */
|
||||
#define BMASK 0xFF /* To extract least significant 8 bits from an int. */
|
||||
|
||||
/* ARGSUSED */
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
# define prog argv[0]
|
||||
{
|
||||
register char **arg = argv;
|
||||
struct outhead header;
|
||||
|
||||
while (*++arg) {
|
||||
if (! rd_open(*arg)) {
|
||||
error("%s: cannot read %s\n", prog, *arg);
|
||||
continue;
|
||||
}
|
||||
rd_ohead(&header);
|
||||
if (BADMAGIC(header)) {
|
||||
error("%s: %s not an ACK object file\n", prog, *arg);
|
||||
} else {
|
||||
printf("%s:\n", *arg);
|
||||
show(&header);
|
||||
}
|
||||
rd_close();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read an ACK object file from `fp' and show it in a human readable way.
|
||||
* NB. The header has already been read and is in the struct outhead `headp'
|
||||
* points to.
|
||||
*/
|
||||
show(headp)
|
||||
register struct outhead *headp;
|
||||
{
|
||||
register int i;
|
||||
register struct outname *np;
|
||||
register struct outname *name; /* Dynamically allocated name-array. */
|
||||
register char *string;/* Base of string area. */
|
||||
extern char *myalloc();
|
||||
|
||||
printf("Version %d\n", headp->oh_stamp);
|
||||
showflags((unsigned) headp->oh_flags);
|
||||
/*
|
||||
* Show all sections.
|
||||
*/
|
||||
for (i = 0; i < headp->oh_nsect; i++) {
|
||||
printf("Section %d:\n", i);
|
||||
showsect();
|
||||
}
|
||||
/*
|
||||
* Show relocation information.
|
||||
*/
|
||||
for (i = 0; i < headp->oh_nrelo; i++) {
|
||||
printf("Relocation record %d:\n", i);
|
||||
showrelo();
|
||||
}
|
||||
/*
|
||||
* We get all struct outname's and the strings in core first.
|
||||
*/
|
||||
name = (struct outname *) myalloc(headp->oh_nname * SZ_NAME);
|
||||
string = myalloc((unsigned) headp->oh_nchar);
|
||||
rd_name(name, headp->oh_nname);
|
||||
for (np = &name[0]; np < &name[headp->oh_nname]; np++) {
|
||||
if (np->on_foff != 0) {
|
||||
np->on_foff -= OFF_CHAR(*headp);
|
||||
if (np->on_foff >= headp->oh_nchar || np->on_foff < 0) {
|
||||
np->on_mptr = "????";
|
||||
}
|
||||
else np->on_mptr = string + np->on_foff;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Transfer strings from file to core.
|
||||
*/
|
||||
rd_string(string, headp->oh_nchar);
|
||||
/*
|
||||
* Now we can show all names.
|
||||
*/
|
||||
for (np = &name[0]; np < &name[headp->oh_nname]; np++) {
|
||||
printf("Name %d:\n", np - name);
|
||||
showname(np);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Show flags from header.
|
||||
*/
|
||||
showflags(flagword)
|
||||
unsigned flagword;
|
||||
{
|
||||
if (flagword & HF_LINK) printf("unresolved references left\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* Show a section.
|
||||
*/
|
||||
showsect()
|
||||
{
|
||||
struct outsect section;
|
||||
|
||||
rd_sect(§ion, 1);
|
||||
printf("\tstartaddress in machine\t%ld\n", section.os_base);
|
||||
printf("\tsection size in machine\t%ld\n", section.os_size);
|
||||
printf("\tstartaddress in file\t%ld\n", section.os_foff);
|
||||
printf("\tsection size in file\t%ld\n", section.os_flen);
|
||||
printf("\tsection alignment\t%ld\n", section.os_lign);
|
||||
}
|
||||
|
||||
/*
|
||||
* Show a relocation record.
|
||||
*/
|
||||
showrelo()
|
||||
{
|
||||
struct outrelo relrec;
|
||||
|
||||
rd_relo(&relrec, 1);
|
||||
switch (relrec.or_type & RELSZ) {
|
||||
case RELO1:
|
||||
printf("\t1 byte\n");
|
||||
break;
|
||||
case RELO2:
|
||||
printf("\t2 bytes\n");
|
||||
break;
|
||||
case RELO4:
|
||||
printf("\t4 bytes\n");
|
||||
break;
|
||||
default:
|
||||
error("\tunexpected relocation length\n");
|
||||
break;
|
||||
}
|
||||
if (relrec.or_type & RELPC) printf("\tpc relative\n");
|
||||
if (relrec.or_type & RELBR) printf("\tbytes reversed\n");
|
||||
if (relrec.or_type & RELWR) printf("\twords reversed\n");
|
||||
printf("\treferencing section\t%d\n", (relrec.or_sect & BMASK) - S_MIN);
|
||||
printf("\treferenced symbol index\t%d\n", relrec.or_nami);
|
||||
printf("\treferencing address\t%ld\n", relrec.or_addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Show the name in the struct `namep' points to.
|
||||
*/
|
||||
showname(namep)
|
||||
struct outname *namep;
|
||||
{
|
||||
if (namep->on_mptr)
|
||||
printf("\t%s\n", namep->on_mptr);
|
||||
else
|
||||
printf("\tno name\n");
|
||||
switch (namep->on_type & S_TYP) {
|
||||
case S_UND:
|
||||
printf("\tundefined\n");
|
||||
break;
|
||||
case S_ABS:
|
||||
printf("\tabsolute\n");
|
||||
break;
|
||||
case S_CRS:
|
||||
printf("\tcross reference\n");
|
||||
default:
|
||||
printf("\tin section %d\n", (namep->on_type & S_TYP) - S_MIN);
|
||||
break;
|
||||
}
|
||||
if (namep->on_type & S_EXT) printf("\texternal\n");
|
||||
if (namep->on_type & S_STB) {
|
||||
printf("\tstab 0x%x\n", namep->on_type >> 8);
|
||||
printf("\tdesc 0x%x\n", namep->on_desc);
|
||||
}
|
||||
else switch (namep->on_type & S_ETC) {
|
||||
case S_SCT:
|
||||
printf("\tsection name\n"); break;
|
||||
case S_LIN:
|
||||
printf("\thll source line item\n"); break;
|
||||
case S_FIL:
|
||||
printf("\thll source file item\n"); break;
|
||||
case S_MOD:
|
||||
printf("\tass src file item\n"); break;
|
||||
case S_COM:
|
||||
printf("\tcommon\n"); break;
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
printf("\tstab 0x%x\n", namep->on_type >> 8);
|
||||
printf("\tdesc 0x%x\n", namep->on_desc);
|
||||
}
|
||||
printf("\tvalue %ld\n", namep->on_valu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Core allocation via malloc() but fatal if no core.
|
||||
*/
|
||||
char *
|
||||
myalloc(u)
|
||||
unsigned int u;
|
||||
{
|
||||
register char *rcp;
|
||||
extern char *malloc();
|
||||
|
||||
rcp = malloc(u);
|
||||
if (rcp == (char *) 0) {
|
||||
error("Out of core\n");
|
||||
exit(1);
|
||||
}
|
||||
return rcp;
|
||||
}
|
||||
|
||||
/* VARARGS1 */
|
||||
error(s, a1, a2, a3, a4)
|
||||
char *s;
|
||||
{
|
||||
fflush(stdout);
|
||||
fprintf(stderr, s, a1, a2, a3, a4);
|
||||
}
|
||||
|
||||
rd_fatal()
|
||||
{
|
||||
error("Error in reading the object file\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
.TH ASIZE 1 "$Revision$"
|
||||
.SH NAME
|
||||
asize \- size of an object file
|
||||
.SH SYNOPSIS
|
||||
asize [ file ... ]
|
||||
.SH DESCRIPTION
|
||||
.I Asize
|
||||
prints the (decimal) number of bytes
|
||||
required by the different sections,
|
||||
and their sum in decimal and hexadecimal,
|
||||
of each ack.out(5) format object file argument.
|
||||
If no file is specified,
|
||||
`a.out'
|
||||
is used.
|
||||
.SH "SEE ALSO"
|
||||
ack.out(5)
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "out.h"
|
||||
|
||||
/*
|
||||
asize -- determine object size
|
||||
|
||||
*/
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
struct outhead buf;
|
||||
struct outsect sbuf;
|
||||
unsigned short nrsect;
|
||||
long sum;
|
||||
int gorp;
|
||||
|
||||
if (--argc == 0) {
|
||||
argc = 1;
|
||||
argv[1] = "a.out";
|
||||
}
|
||||
gorp = argc;
|
||||
|
||||
while(argc--) {
|
||||
if (! rd_open(*++argv)) {
|
||||
fprintf(stderr, "asize: cannot open %s\n", *argv);
|
||||
continue;
|
||||
}
|
||||
rd_ohead(&buf);
|
||||
if(BADMAGIC(buf)) {
|
||||
fprintf(stderr, "asize: %s-- bad format\n", *argv);
|
||||
rd_close();
|
||||
continue;
|
||||
}
|
||||
nrsect = buf.oh_nsect;
|
||||
if (nrsect == 0) {
|
||||
fprintf(stderr, "asize: %s-- no sections\n", *argv);
|
||||
rd_close();
|
||||
continue;
|
||||
}
|
||||
if (gorp > 1)
|
||||
printf("%s: ", *argv);
|
||||
|
||||
sum = 0;
|
||||
while (nrsect-- > 0) {
|
||||
rd_sect(&sbuf, 1);
|
||||
printf("%ld", sbuf.os_size);
|
||||
sum += sbuf.os_size;
|
||||
if (nrsect > 0)
|
||||
putchar('+');
|
||||
}
|
||||
printf(" = %ld = 0x%lx\n", sum, sum);
|
||||
rd_close();
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
rd_fatal()
|
||||
{
|
||||
fprintf(stderr, "read error\n");
|
||||
exit(2);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
.TH ASTRIP 1 "$Revision$"
|
||||
.SH NAME
|
||||
astrip \- remove symbols and relocation information
|
||||
.SH SYNOPSIS
|
||||
astrip file ...
|
||||
.SH DESCRIPTION
|
||||
.I Astrip
|
||||
removes the symbol
|
||||
table and relocation information ordinarily attached to the
|
||||
ack.out(5) format object files.
|
||||
This is useful to save space after a program has been
|
||||
debugged.
|
||||
.SH FILES
|
||||
/tmp/s? temporary file
|
||||
.SH "SEE ALSO"
|
||||
ack.out(5)
|
||||
@@ -1,152 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* $Id$ */
|
||||
|
||||
#include "out.h"
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
|
||||
astrip -- remove symbols and relocation bits
|
||||
|
||||
*/
|
||||
|
||||
char temp_name[] = "/tmp/sXXXXXX";
|
||||
char *tname;
|
||||
char *mktemp();
|
||||
FILE *fopen();
|
||||
FILE *tf;
|
||||
struct outhead buf;
|
||||
int readerror, writeerror;
|
||||
|
||||
main(argc, argv)
|
||||
char **argv;
|
||||
{
|
||||
int status;
|
||||
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGQUIT, SIG_IGN);
|
||||
tname = mktemp(temp_name);
|
||||
while(--argc) {
|
||||
if ((status = strip(argv[argc])) > 1)
|
||||
break;
|
||||
}
|
||||
unlink(tname);
|
||||
exit(status);
|
||||
}
|
||||
|
||||
extern long lseek();
|
||||
|
||||
strip(name)
|
||||
char *name;
|
||||
{
|
||||
long size;
|
||||
int fw;
|
||||
|
||||
if (! rd_open(name)) {
|
||||
fprintf(stderr, "astrip: cannot open %s\n", name);
|
||||
return(1);
|
||||
}
|
||||
readerror = 0;
|
||||
writeerror = 0;
|
||||
rd_ohead(&buf);
|
||||
if(readerror || BADMAGIC(buf)) {
|
||||
fprintf(stderr, "astrip: %s-- bad format\n", name);
|
||||
rd_close();
|
||||
return(1);
|
||||
}
|
||||
size = OFF_RELO(buf) - SZ_HEAD;
|
||||
buf.oh_flags &= ~HF_LINK;
|
||||
buf.oh_nrelo = 0;
|
||||
buf.oh_nname = 0;
|
||||
buf.oh_nchar = 0;
|
||||
|
||||
|
||||
if (! wr_open(tname)) {
|
||||
fprintf(stderr, "astrip: cannot create temp file %s\n", tname);
|
||||
rd_close();
|
||||
return(2);
|
||||
}
|
||||
wr_ohead(&buf);
|
||||
wr_close();
|
||||
if (writeerror) {
|
||||
fprintf(stderr, "astrip: write error on temp file %s\n", tname);
|
||||
rd_close();
|
||||
return(1);
|
||||
}
|
||||
fw = open(tname, 2);
|
||||
if (fw < 0 || lseek(fw, (long)SZ_HEAD, 0) < 0) {
|
||||
fprintf(stderr, "astrip: cannot create temp file %s\n", tname);
|
||||
rd_close();
|
||||
close(fw);
|
||||
return(2);
|
||||
}
|
||||
if(copy(name, tname, size, rd_fd(), fw)) {
|
||||
rd_close();
|
||||
close(fw);
|
||||
return(1);
|
||||
}
|
||||
rd_close();
|
||||
close(fw);
|
||||
size += SZ_HEAD;
|
||||
if (! rd_open(tname)) {
|
||||
fprintf(stderr, "astrip: cannot read temp file %s\n", tname);
|
||||
return(2);
|
||||
}
|
||||
fw = creat(name, 0777);
|
||||
if (fw < 0) {
|
||||
fprintf(stderr, "astrip: cannot write %s\n", name);
|
||||
rd_close();
|
||||
return(1);
|
||||
}
|
||||
if(copy(tname, name, size, rd_fd(), fw)) {
|
||||
close(fw);
|
||||
rd_close();
|
||||
return(2);
|
||||
}
|
||||
|
||||
close(fw);
|
||||
rd_close();
|
||||
return(0);
|
||||
}
|
||||
|
||||
copy(fnam, tnam, size, fr, fw)
|
||||
char *fnam;
|
||||
char *tnam;
|
||||
long size;
|
||||
{
|
||||
register s, n;
|
||||
char lbuf[512];
|
||||
|
||||
while(size != (long)0) {
|
||||
s = 512;
|
||||
if(size < 512)
|
||||
s = (int) size;
|
||||
rd_bytes(fr, lbuf, (long) s);
|
||||
if (readerror) {
|
||||
fprintf(stderr, "astrip: unexpected eof on %s\n", fnam);
|
||||
return(1);
|
||||
}
|
||||
wr_bytes(fw, lbuf, (long) s);
|
||||
if (writeerror) {
|
||||
fprintf(stderr, "astrip: write error on %s\n", tnam);
|
||||
return(1);
|
||||
}
|
||||
size -= (long)s;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
rd_fatal()
|
||||
{
|
||||
readerror = 1;
|
||||
}
|
||||
|
||||
wr_fatal()
|
||||
{
|
||||
writeerror = 1;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
#PARAMS do not remove this line!
|
||||
|
||||
SRC_DIR = $(SRC_HOME)/util/amisc
|
||||
BINDIR = $(TARGET_HOME)/bin
|
||||
LDFLAGS = $(LDOPTIONS)
|
||||
INCLUDES = -I$(TARGET_HOME)/h
|
||||
CFLAGS = $(INCLUDES) $(COPTIONS)
|
||||
LINTFLAGS = $(INCLUDES) $(LINTOPTIONS)
|
||||
|
||||
ALL = anm asize astrip ashow
|
||||
LIBS = $(TARGET_HOME)/modules/lib/libobject.$(LIBSUF)
|
||||
LINTLIBS = $(UTIL_HOME)/modules/lib/$(LINTPREF)object.$(LINTSUF)
|
||||
|
||||
all: $(ALL)
|
||||
|
||||
anm: $(SRC_DIR)/anm.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o anm $(SRC_DIR)/anm.c $(LIBS)
|
||||
asize: $(SRC_DIR)/asize.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o asize $(SRC_DIR)/asize.c $(LIBS)
|
||||
astrip: $(SRC_DIR)/astrip.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o astrip $(SRC_DIR)/astrip.c $(LIBS)
|
||||
ashow: $(SRC_DIR)/ashow.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o ashow $(SRC_DIR)/ashow.c $(LIBS)
|
||||
|
||||
install: all
|
||||
for i in $(ALL); do rm -f $(BINDIR)/$$i; cp $$i $(BINDIR)/$$i; done
|
||||
if [ $(DO_MACHINE_INDEP) = y ] ; \
|
||||
then for i in anm.1 asize.1 astrip.1; do mk_manpage $(SRC_DIR)/$$i $(TARGET_HOME) ; done ; \
|
||||
fi
|
||||
|
||||
cmp: all
|
||||
-for i in $(ALL); do cmp $$i $(BINDIR)/$$i; done
|
||||
|
||||
clean: ; rm -f $(ALL) *.$(SUF)
|
||||
|
||||
lint:
|
||||
$(LINT) $(LINTFLAGS) $(SRC_DIR)/anm.c $(LINTLIBS)
|
||||
$(LINT) $(LINTFLAGS) $(SRC_DIR)/asize.c $(LINTLIBS)
|
||||
$(LINT) $(LINTFLAGS) $(SRC_DIR)/astrip.c $(LINTLIBS)
|
||||
$(LINT) $(LINTFLAGS) $(SRC_DIR)/ashow.c $(LINTLIBS)
|
||||
|
||||
pr:
|
||||
@pr $(SRC_DIR)/proto.make $(SRC_DIR)/anm.c $(SRC_DIR)/astrip.c $(SRC_DIR)/asize.c $(SRC_DIR)/ashow.c
|
||||
|
||||
opr:
|
||||
make pr | opr
|
||||
@@ -1,5 +0,0 @@
|
||||
proto.make
|
||||
aal.1
|
||||
arch.1
|
||||
arch.5
|
||||
archiver.c
|
||||
@@ -1,50 +0,0 @@
|
||||
EMHOME = ../..
|
||||
EMH = $(EMHOME)/h
|
||||
EMBIN = $(EMHOME)/bin
|
||||
LIB = $(EMHOME)/modules/lib
|
||||
|
||||
LIBS = $(LIB)/libobject.a $(LIB)/libprint.a \
|
||||
$(LIB)/libstring.a $(LIB)/libsystem.a
|
||||
|
||||
CFLAGS=-O -I$(EMH) -DDISTRIBUTION
|
||||
LDFLAGS =
|
||||
|
||||
all: arch aal
|
||||
|
||||
arch: arch.o
|
||||
$(CC) $(LDFLAGS) -o arch arch.o $(LIBS)
|
||||
|
||||
aal: aal.o
|
||||
$(CC) $(LDFLAGS) -o aal aal.o $(LIBS)
|
||||
|
||||
arch.o: $(EMH)/arch.h archiver.c
|
||||
$(CC) $(CFLAGS) -c archiver.c
|
||||
mv archiver.o arch.o
|
||||
|
||||
aal.o: $(EMH)/arch.h archiver.c $(EMH)/ranlib.h $(EMH)/out.h
|
||||
$(CC) -DAAL $(CFLAGS) -c archiver.c
|
||||
mv archiver.o aal.o
|
||||
|
||||
clean:
|
||||
rm -f aal arch *.o *.old
|
||||
|
||||
install : all
|
||||
rm -f $(EMBIN)/arch $(EMBIN)/aal
|
||||
cp aal $(EMBIN)/aal
|
||||
cp arch $(EMBIN)/arch
|
||||
rm -f $(EMHOME)/man/arch.1 $(EMHOME)/man/aal.1 $(EMHOME)/man/arch.5
|
||||
cp aal.1 $(EMHOME)/man/aal.1
|
||||
cp arch.1 $(EMHOME)/man/arch.1
|
||||
cp arch.5 $(EMHOME)/man/arch.5
|
||||
|
||||
cmp : all
|
||||
-cmp aal $(EMBIN)/aal
|
||||
-cmp arch $(EMBIN)/arch
|
||||
-cmp aal.1 $(EMHOME)/man/aal.1
|
||||
-cmp arch.1 $(EMHOME)/man/arch.1
|
||||
-cmp arch.5 $(EMHOME)/man/arch.5
|
||||
|
||||
opr:
|
||||
make pr ^ opr
|
||||
pr:
|
||||
@pr Makefile archiver.c
|
||||
@@ -1,90 +0,0 @@
|
||||
.\" $Id$
|
||||
.TH AAL 1 "$Revision$"
|
||||
.ad
|
||||
.SH NAME
|
||||
aal \- archive and library maintainer
|
||||
.SH SYNOPSIS
|
||||
.B aal
|
||||
key afile name ...
|
||||
.SH DESCRIPTION
|
||||
.I Aal
|
||||
maintains groups of ACK-object files
|
||||
combined into a single archive file.
|
||||
An index-table is automatically maintained.
|
||||
The link editor
|
||||
.IR led (6)
|
||||
only understands archives made with
|
||||
.IR aal .
|
||||
.PP
|
||||
.I Key
|
||||
is one character from the set
|
||||
.B qdrtx,
|
||||
optionally concatenated with
|
||||
one or more of
|
||||
.B vlc.
|
||||
.I Afile
|
||||
is the archive file.
|
||||
The
|
||||
.I names
|
||||
are constituent files in the archive file.
|
||||
The meanings of the
|
||||
.I key
|
||||
characters are:
|
||||
.TP
|
||||
.B d
|
||||
Delete the named files from the archive file.
|
||||
.TP
|
||||
.B q
|
||||
Append the named files to the archive file.
|
||||
.TP
|
||||
.B r
|
||||
Replace the named files in the archive file.
|
||||
New files are placed at the end.
|
||||
.TP
|
||||
.B t
|
||||
Print a table of contents of the archive file.
|
||||
If no names are given, all files in the archive are listed.
|
||||
If names are given, only those files are listed.
|
||||
.TP
|
||||
.B x
|
||||
Extract the named files.
|
||||
If no names are given, all files in the archive are
|
||||
extracted.
|
||||
In neither case does
|
||||
.B x
|
||||
alter the archive file.
|
||||
.TP
|
||||
.B v
|
||||
Verbose.
|
||||
Under the verbose option,
|
||||
.I aal
|
||||
gives a file-by-file
|
||||
description of the making of a
|
||||
new archive file from the old archive and the constituent files.
|
||||
When used with
|
||||
.B t,
|
||||
it gives a long listing of all information about the files.
|
||||
.TP
|
||||
.B l
|
||||
Local.
|
||||
Normally
|
||||
.I aal
|
||||
places its temporary files in the directory /tmp.
|
||||
This option causes them to be placed in the local directory.
|
||||
.TP
|
||||
.B c
|
||||
Create. Normally
|
||||
.I aal
|
||||
will create
|
||||
.I afile
|
||||
when it needs to.
|
||||
The create option supresses the normal message that is produced when
|
||||
.I afile
|
||||
is created.
|
||||
.SH FILES
|
||||
/tmp/ar.* temporaries
|
||||
.SH "SEE ALSO"
|
||||
led(6), arch(5),
|
||||
.SH BUGS
|
||||
If the same file is mentioned twice in an argument list,
|
||||
it may be put in the archive twice.
|
||||
@@ -1,94 +0,0 @@
|
||||
.\" $Id$
|
||||
.TH ARCH 1 "$Revision$"
|
||||
.ad
|
||||
.SH NAME
|
||||
arch \- archive and library maintainer
|
||||
.SH SYNOPSIS
|
||||
.B arch
|
||||
key afile name ...
|
||||
.SH DESCRIPTION
|
||||
.I Arch
|
||||
maintains groups of files
|
||||
combined into a single archive file.
|
||||
The Amsterdam compiler kit provides its own archiver with a
|
||||
fixed, machine-independent format, much like the UNIX-V7
|
||||
archive format.
|
||||
.PP
|
||||
.I Key
|
||||
is one character from the set
|
||||
.B qdrtpx,
|
||||
optionally concatenated with
|
||||
one or more of
|
||||
.B vlc.
|
||||
.I Afile
|
||||
is the archive file.
|
||||
The
|
||||
.I names
|
||||
are constituent files in the archive file.
|
||||
The meanings of the
|
||||
.I key
|
||||
characters are:
|
||||
.TP
|
||||
.B d
|
||||
Delete the named files from the archive file.
|
||||
.TP
|
||||
.B q
|
||||
Append the named files to the archive file.
|
||||
.TP
|
||||
.B r
|
||||
Replace the named files in the archive file.
|
||||
New files are placed at the end.
|
||||
.TP
|
||||
.B t
|
||||
Print a table of contents of the archive file.
|
||||
If no names are given, all files in the archive are listed.
|
||||
If names are given, only those files are listed.
|
||||
.TP
|
||||
.B p
|
||||
Print the named files in the archive.
|
||||
.TP
|
||||
.B x
|
||||
Extract the named files.
|
||||
If no names are given, all files in the archive are
|
||||
extracted.
|
||||
In neither case does
|
||||
.B x
|
||||
alter the archive file.
|
||||
.TP
|
||||
.B v
|
||||
Verbose.
|
||||
Under the verbose option,
|
||||
.I arch
|
||||
gives a file-by-file
|
||||
description of the making of a
|
||||
new archive file from the old archive and the constituent files.
|
||||
When used with
|
||||
.B t,
|
||||
it gives a long listing of all information about the files.
|
||||
When used with
|
||||
.BR p ,
|
||||
it precedes each file with a name.
|
||||
.TP
|
||||
.B l
|
||||
Local.
|
||||
Normally
|
||||
.I arch
|
||||
places its temporary files in the directory /tmp.
|
||||
This option causes them to be placed in the local directory.
|
||||
.TP
|
||||
.B c
|
||||
Create. Normally
|
||||
.I arch
|
||||
will create
|
||||
.I afile
|
||||
when it needs to.
|
||||
The create option supresses the normal message that is produced when
|
||||
.I afile
|
||||
is created.
|
||||
.SH FILES
|
||||
/tmp/ar.* temporaries
|
||||
.SH "SEE ALSO"
|
||||
em_ass(1), arch(5),
|
||||
.SH BUGS
|
||||
If the same file is mentioned twice in an argument list,
|
||||
it may be put in the archive twice.
|
||||
@@ -1,55 +0,0 @@
|
||||
.\" $Id$
|
||||
.TH ARCH 5 "$Revision$"
|
||||
.ad
|
||||
.SH NAME
|
||||
arch \- archive (library) file format
|
||||
.SH SYNOPSIS
|
||||
.B #include <arch.h>
|
||||
.SH DESCRIPTION
|
||||
The archive command
|
||||
.I arch
|
||||
is used to combine several files into
|
||||
one.
|
||||
Archives are used mainly as libraries to be searched
|
||||
by the EM assembler/linker em_ass(6) or the universal
|
||||
assembler/linker uni_ass(6).
|
||||
.PP
|
||||
A file produced by
|
||||
.I arch
|
||||
has a magic number at the start,
|
||||
followed by the constituent files, each preceded by a file header.
|
||||
The magic number and header layout as described in the
|
||||
include file are:
|
||||
.RS
|
||||
.PP
|
||||
.nf
|
||||
.ta \w'#define 'u +\w'ARMAG 'u
|
||||
.so ../../h/arch.h
|
||||
.fi
|
||||
.RE
|
||||
.LP
|
||||
The name is a null-terminated string;
|
||||
The sizes of the other entries are determined as follows:
|
||||
long's are 4 bytes in PDP-11 order, int are 2 bytes, low order
|
||||
byte first, char's are 1 byte.
|
||||
The date is in the
|
||||
form of
|
||||
.IR time (2);
|
||||
the user ID and group ID are numbers; the mode is a bit pattern
|
||||
per
|
||||
.IR chmod (2);
|
||||
the size is counted in bytes.
|
||||
.PP
|
||||
Each file begins on a even offset;
|
||||
a null byte is inserted between files if necessary.
|
||||
Nevertheless the size given reflects the
|
||||
actual size of the file exclusive of padding.
|
||||
.PP
|
||||
Notice there is no provision for empty areas in an archive
|
||||
file.
|
||||
.SH FILES
|
||||
~em/h/arch.h
|
||||
.SH "SEE ALSO"
|
||||
arch(1), em_ass(6), uni_ass(6)
|
||||
.SH BUGS
|
||||
Coding user and group IDs as characters is a botch.
|
||||
@@ -1,769 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* ar - archiver Author: Michiel Huisjes */
|
||||
/* Made into arch/aal by Ceriel Jacobs
|
||||
*/
|
||||
|
||||
static char RcsId[] = "$Id$";
|
||||
|
||||
/*
|
||||
* Usage: [arch|aal] [qdprtx][vlcu] archive [file] ...
|
||||
* v: verbose
|
||||
* x: extract
|
||||
* q: append
|
||||
* r: replace (append when not in archive)
|
||||
* d: delete
|
||||
* t: print contents of archive
|
||||
* p: print named files
|
||||
* l: temporaries in current directory instead of /tmp
|
||||
* c: don't give "create" message
|
||||
* u: replace only if dated later than member in archive
|
||||
#ifdef DISTRIBUTION
|
||||
* D: make distribution: use distr_time, uid=2, gid=2, mode=0644
|
||||
#endif
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <signal.h>
|
||||
#include <arch.h>
|
||||
#include <ranlib.h>
|
||||
#ifdef AAL
|
||||
#include <out.h>
|
||||
#define MAGIC_NUMBER AALMAG
|
||||
long offset;
|
||||
struct ranlib *tab;
|
||||
unsigned int tnum = 0;
|
||||
char *tstrtab;
|
||||
unsigned int tssiz = 0;
|
||||
char *malloc(), *realloc(), *strcpy(), *strncpy();
|
||||
long time();
|
||||
unsigned int tabsz, strtabsz;
|
||||
#else
|
||||
#define MAGIC_NUMBER ARMAG
|
||||
#endif
|
||||
long lseek();
|
||||
|
||||
#define odd(nr) (nr & 01)
|
||||
#define even(nr) (odd(nr) ? nr + 1 : nr)
|
||||
|
||||
typedef char BOOL;
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
#define READ 0
|
||||
#define APPEND 2
|
||||
#define CREATE 1
|
||||
|
||||
#define MEMBER struct ar_hdr
|
||||
|
||||
#define NIL_PTR ((char *) 0)
|
||||
#define NIL_MEM ((MEMBER *) 0)
|
||||
#define NIL_LONG ((long *) 0)
|
||||
|
||||
#define IO_SIZE (10 * 1024)
|
||||
|
||||
#define equal(str1, str2) (!strncmp((str1), (str2), 14))
|
||||
#ifndef S_ISDIR
|
||||
#define S_ISDIR(m) (m & S_IFDIR) /* is a directory */
|
||||
#endif
|
||||
|
||||
BOOL verbose;
|
||||
BOOL app_fl;
|
||||
BOOL ex_fl;
|
||||
BOOL show_fl;
|
||||
BOOL pr_fl;
|
||||
BOOL u_fl;
|
||||
BOOL rep_fl;
|
||||
BOOL del_fl;
|
||||
BOOL nocr_fl;
|
||||
BOOL local_fl;
|
||||
#ifdef DISTRIBUTION
|
||||
BOOL distr_fl;
|
||||
long distr_time;
|
||||
#endif
|
||||
|
||||
int ar_fd;
|
||||
|
||||
char io_buffer[IO_SIZE];
|
||||
|
||||
char *progname;
|
||||
|
||||
char temp_buf[32];
|
||||
char *temp_arch = &temp_buf[0];
|
||||
extern char *mktemp();
|
||||
extern char *ctime();
|
||||
|
||||
usage()
|
||||
{
|
||||
error(TRUE, "usage: %s [qdprtxl][vlc] archive [file] ...\n",
|
||||
progname
|
||||
);
|
||||
}
|
||||
|
||||
/*VARARGS2*/
|
||||
error(quit, str1, str2, str3, str4)
|
||||
BOOL quit;
|
||||
char *str1, *str2, *str3, *str4;
|
||||
{
|
||||
char errbuf[256];
|
||||
|
||||
sprint(errbuf, str1, str2, str3, str4);
|
||||
write(2, errbuf, strlen(errbuf));
|
||||
if (quit) {
|
||||
unlink(temp_arch);
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
char *basename(path)
|
||||
char *path;
|
||||
{
|
||||
register char *ptr = path;
|
||||
register char *last = NIL_PTR;
|
||||
|
||||
while (*ptr != '\0') {
|
||||
if (*ptr == '/')
|
||||
last = ptr;
|
||||
ptr++;
|
||||
}
|
||||
if (last == NIL_PTR)
|
||||
return path;
|
||||
if (*(last + 1) == '\0') {
|
||||
*last = '\0';
|
||||
return basename(path);
|
||||
}
|
||||
return last + 1;
|
||||
}
|
||||
|
||||
extern unsigned int rd_unsigned2();
|
||||
|
||||
open_archive(name, mode)
|
||||
register char *name;
|
||||
register int mode;
|
||||
{
|
||||
unsigned short magic = 0;
|
||||
int fd;
|
||||
|
||||
if (mode == CREATE) {
|
||||
if ((fd = creat(name, 0666)) < 0)
|
||||
error(TRUE, "cannot creat %s\n", name);
|
||||
magic = MAGIC_NUMBER;
|
||||
wr_int2(fd, magic);
|
||||
return fd;
|
||||
}
|
||||
|
||||
if ((fd = open(name, mode)) < 0) {
|
||||
if (mode == APPEND) {
|
||||
close(open_archive(name, CREATE));
|
||||
if (!nocr_fl) error(FALSE, "%s: creating %s\n", progname, name);
|
||||
return open_archive(name, APPEND);
|
||||
}
|
||||
error(TRUE, "cannot open %s\n", name);
|
||||
}
|
||||
lseek(fd, 0L, 0);
|
||||
magic = rd_unsigned2(fd);
|
||||
if (magic != AALMAG && magic != ARMAG)
|
||||
error(TRUE, "%s is not in ar format\n", name);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
void
|
||||
catch()
|
||||
{
|
||||
unlink(temp_arch);
|
||||
_exit (2);
|
||||
}
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
register char *ptr;
|
||||
int needs_arg = 0;
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
if (argc < 3)
|
||||
usage();
|
||||
|
||||
for (ptr = argv[1]; *ptr; ptr++) {
|
||||
switch (*ptr) {
|
||||
case 't' :
|
||||
show_fl = TRUE;
|
||||
break;
|
||||
case 'v' :
|
||||
verbose = TRUE;
|
||||
break;
|
||||
case 'x' :
|
||||
ex_fl = TRUE;
|
||||
break;
|
||||
case 'q' :
|
||||
needs_arg = 1;
|
||||
app_fl = TRUE;
|
||||
break;
|
||||
case 'c' :
|
||||
nocr_fl = TRUE;
|
||||
break;
|
||||
case 'u':
|
||||
u_fl = TRUE;
|
||||
break;
|
||||
case 'p' :
|
||||
needs_arg = 1;
|
||||
pr_fl = TRUE;
|
||||
break;
|
||||
case 'd' :
|
||||
needs_arg = 1;
|
||||
del_fl = TRUE;
|
||||
break;
|
||||
case 'r' :
|
||||
needs_arg = 1;
|
||||
rep_fl = TRUE;
|
||||
break;
|
||||
case 'l' :
|
||||
local_fl = TRUE;
|
||||
break;
|
||||
#ifdef DISTRIBUTION
|
||||
case 'D' :
|
||||
distr_fl = TRUE;
|
||||
break;
|
||||
#endif
|
||||
default :
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_arg && argc <= 3)
|
||||
usage();
|
||||
#ifdef DISTRIBUTION
|
||||
if (distr_fl) {
|
||||
static struct stat statbuf;
|
||||
|
||||
stat(progname, &statbuf);
|
||||
distr_time = statbuf.st_mtime;
|
||||
}
|
||||
#endif
|
||||
if (local_fl) strcpy(temp_arch, "ar.XXXXXX");
|
||||
else strcpy(temp_arch, "/tmp/ar.XXXXXX");
|
||||
|
||||
if (app_fl + ex_fl + del_fl + rep_fl + show_fl + pr_fl != 1)
|
||||
usage();
|
||||
|
||||
if (u_fl && ! rep_fl)
|
||||
usage();
|
||||
|
||||
if (rep_fl || del_fl
|
||||
#ifdef AAL
|
||||
|| app_fl
|
||||
#endif
|
||||
) {
|
||||
mktemp(temp_arch);
|
||||
}
|
||||
#ifdef AAL
|
||||
tab = (struct ranlib *) malloc(512 * sizeof(struct ranlib));
|
||||
tstrtab = malloc(4096);
|
||||
if (!tab || !tstrtab) error(TRUE,"Out of core\n");
|
||||
tabsz = 512;
|
||||
strtabsz = 4096;
|
||||
#endif
|
||||
|
||||
signal(SIGINT, catch);
|
||||
get(argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MEMBER *
|
||||
get_member()
|
||||
{
|
||||
static MEMBER member;
|
||||
|
||||
again:
|
||||
if (rd_arhdr(ar_fd, &member) == 0)
|
||||
return NIL_MEM;
|
||||
if (member.ar_size < 0) {
|
||||
error(TRUE, "archive has member with negative size\n");
|
||||
}
|
||||
if (equal(SYMDEF, member.ar_name)) {
|
||||
lseek(ar_fd, member.ar_size, 1);
|
||||
goto again;
|
||||
}
|
||||
return &member;
|
||||
}
|
||||
|
||||
char *get_mode();
|
||||
|
||||
get(argc, argv)
|
||||
int argc;
|
||||
register char *argv[];
|
||||
{
|
||||
register MEMBER *member;
|
||||
int i = 0;
|
||||
int temp_fd, read_chars;
|
||||
|
||||
ar_fd = open_archive(argv[2], (show_fl || pr_fl || ex_fl) ? READ : APPEND);
|
||||
if (rep_fl || del_fl
|
||||
#ifdef AAL
|
||||
|| app_fl
|
||||
#endif
|
||||
)
|
||||
temp_fd = open_archive(temp_arch, CREATE);
|
||||
while ((member = get_member()) != NIL_MEM) {
|
||||
if (argc > 3) {
|
||||
for (i = 3; i < argc; i++) {
|
||||
if (equal(basename(argv[i]), member->ar_name))
|
||||
break;
|
||||
}
|
||||
if (i == argc || app_fl) {
|
||||
if (rep_fl || del_fl
|
||||
#ifdef AAL
|
||||
|| app_fl
|
||||
#endif
|
||||
) {
|
||||
#ifdef AAL
|
||||
if (i != argc) {
|
||||
print("%s: already in archive\n", argv[i]);
|
||||
argv[i] = "";
|
||||
}
|
||||
#endif
|
||||
wr_arhdr(temp_fd, member);
|
||||
copy_member(member, ar_fd, temp_fd, 0);
|
||||
}
|
||||
else {
|
||||
#ifndef AAL
|
||||
if (app_fl && i != argc) {
|
||||
print("%s: already in archive\n", argv[i]);
|
||||
argv[i] = "";
|
||||
}
|
||||
#endif
|
||||
lseek(ar_fd, even(member->ar_size),1);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (ex_fl || pr_fl)
|
||||
extract(member);
|
||||
else {
|
||||
if (rep_fl)
|
||||
add(argv[i], temp_fd, "r - %s\n");
|
||||
else if (show_fl) {
|
||||
char buf[sizeof(member->ar_name) + 2];
|
||||
register char *p = buf, *q = member->ar_name;
|
||||
|
||||
while (q <= &member->ar_name[sizeof(member->ar_name)-1] && *q) {
|
||||
*p++ = *q++;
|
||||
}
|
||||
*p++ = '\n';
|
||||
*p = '\0';
|
||||
if (verbose) {
|
||||
char *mode = get_mode(member->ar_mode);
|
||||
char *date = ctime(&(member->ar_date));
|
||||
|
||||
*(date + 16) = '\0';
|
||||
*(date + 24) = '\0';
|
||||
|
||||
print("%s%3u/%u%7ld %s %s %s",
|
||||
mode,
|
||||
(unsigned) (member->ar_uid & 0377),
|
||||
(unsigned) (member->ar_gid & 0377),
|
||||
member->ar_size,
|
||||
date+4,
|
||||
date+20,
|
||||
buf);
|
||||
}
|
||||
else print(buf);
|
||||
}
|
||||
else if (del_fl)
|
||||
show("d - %s\n", member->ar_name);
|
||||
lseek(ar_fd, even(member->ar_size), 1);
|
||||
}
|
||||
argv[i] = "";
|
||||
}
|
||||
|
||||
if (argc > 3) {
|
||||
for (i = 3; i < argc; i++)
|
||||
if (argv[i][0] != '\0') {
|
||||
#ifndef AAL
|
||||
if (app_fl)
|
||||
add(argv[i], ar_fd, "a - %s\n");
|
||||
else
|
||||
#endif
|
||||
if (rep_fl
|
||||
#ifdef AAL
|
||||
|| app_fl
|
||||
#endif
|
||||
)
|
||||
add(argv[i], temp_fd, "a - %s\n");
|
||||
else {
|
||||
print("%s: not found\n", argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rep_fl || del_fl
|
||||
#ifdef AAL
|
||||
|| app_fl
|
||||
#endif
|
||||
) {
|
||||
signal(SIGINT, SIG_IGN);
|
||||
close(ar_fd);
|
||||
close(temp_fd);
|
||||
ar_fd = open_archive(argv[2], CREATE);
|
||||
temp_fd = open_archive(temp_arch, APPEND);
|
||||
#ifdef AAL
|
||||
write_symdef();
|
||||
#endif
|
||||
while ((read_chars = read(temp_fd, io_buffer, IO_SIZE)) > 0)
|
||||
mwrite(ar_fd, io_buffer, read_chars);
|
||||
close(temp_fd);
|
||||
unlink(temp_arch);
|
||||
}
|
||||
close(ar_fd);
|
||||
}
|
||||
|
||||
add(name, fd, mess)
|
||||
char *name;
|
||||
int fd;
|
||||
char *mess;
|
||||
{
|
||||
static MEMBER member;
|
||||
register int read_chars;
|
||||
struct stat status;
|
||||
int src_fd;
|
||||
|
||||
if (stat(name, &status) < 0) {
|
||||
error(FALSE, "cannot find %s\n", name);
|
||||
return;
|
||||
}
|
||||
else if (S_ISDIR(status.st_mode)) {
|
||||
error(FALSE, "%s is a directory (ignored)\n", name);
|
||||
return;
|
||||
}
|
||||
else if (u_fl && status.st_mtime <= member.ar_date) {
|
||||
wr_arhdr(fd, member);
|
||||
copy_member(member, ar_fd, fd, 0);
|
||||
return;
|
||||
}
|
||||
else if ((src_fd = open(name, 0)) < 0) {
|
||||
error(FALSE, "cannot open %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
strncpy (member.ar_name, basename (name), sizeof(member.ar_name));
|
||||
member.ar_uid = status.st_uid;
|
||||
member.ar_gid = status.st_gid;
|
||||
member.ar_mode = status.st_mode;
|
||||
member.ar_date = status.st_mtime;
|
||||
member.ar_size = status.st_size;
|
||||
#ifdef DISTRIBUTION
|
||||
if (distr_fl) {
|
||||
member.ar_uid = 2;
|
||||
member.ar_gid = 2;
|
||||
member.ar_mode = 0644;
|
||||
member.ar_date = distr_time;
|
||||
}
|
||||
#endif
|
||||
wr_arhdr(fd, &member);
|
||||
#ifdef AAL
|
||||
do_object(src_fd, member.ar_size);
|
||||
lseek(src_fd, 0L, 0);
|
||||
offset += AR_TOTAL + even(member.ar_size);
|
||||
#endif
|
||||
while (status.st_size > 0) {
|
||||
int x = IO_SIZE;
|
||||
|
||||
read_chars = x;
|
||||
if (status.st_size < x) {
|
||||
x = status.st_size;
|
||||
read_chars = x;
|
||||
status.st_size = 0;
|
||||
x = even(x);
|
||||
}
|
||||
else status.st_size -= x;
|
||||
if (read(src_fd, io_buffer, read_chars) != read_chars) {
|
||||
error(FALSE,"%s seems to shrink\n", name);
|
||||
break;
|
||||
}
|
||||
mwrite(fd, io_buffer, x);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
show(mess, member.ar_name);
|
||||
close(src_fd);
|
||||
}
|
||||
|
||||
extract(member)
|
||||
register MEMBER *member;
|
||||
{
|
||||
int fd = 1;
|
||||
char buf[sizeof(member->ar_name) + 1];
|
||||
|
||||
strncpy(buf, member->ar_name, sizeof(member->ar_name));
|
||||
buf[sizeof(member->ar_name)] = 0;
|
||||
if (pr_fl == FALSE && (fd = creat(buf, 0666)) < 0) {
|
||||
error(FALSE, "cannot create %s\n", buf);
|
||||
fd = -1;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
if (pr_fl == FALSE) show("x - %s\n", buf);
|
||||
else show("\n<%s>\n\n", buf);
|
||||
}
|
||||
|
||||
copy_member(member, ar_fd, fd, 1);
|
||||
|
||||
if (fd >= 0 && fd != 1)
|
||||
close(fd);
|
||||
if (pr_fl == FALSE) chmod(buf, member->ar_mode);
|
||||
}
|
||||
|
||||
copy_member(member, from, to, extracting)
|
||||
register MEMBER *member;
|
||||
int from, to;
|
||||
{
|
||||
register int rest;
|
||||
long mem_size = member->ar_size;
|
||||
BOOL is_odd = odd(mem_size) ? TRUE : FALSE;
|
||||
|
||||
#ifdef AAL
|
||||
if (! extracting) {
|
||||
long pos = lseek(from, 0L, 1);
|
||||
|
||||
do_object(from, mem_size);
|
||||
offset += AR_TOTAL + even(mem_size);
|
||||
lseek(from, pos, 0);
|
||||
}
|
||||
#endif
|
||||
do {
|
||||
rest = mem_size > (long) IO_SIZE ? IO_SIZE : (int) mem_size;
|
||||
if (read(from, io_buffer, rest) != rest) {
|
||||
char buf[sizeof(member->ar_name) + 1];
|
||||
|
||||
strncpy(buf, member->ar_name, sizeof(member->ar_name));
|
||||
buf[sizeof(member->ar_name)] = 0;
|
||||
error(TRUE, "read error on %s\n", buf);
|
||||
}
|
||||
if (to >= 0) mwrite(to, io_buffer, rest);
|
||||
mem_size -= (long) rest;
|
||||
} while (mem_size > 0L);
|
||||
|
||||
if (is_odd) {
|
||||
lseek(from, 1L, 1);
|
||||
if (to >= 0 && ! extracting)
|
||||
lseek(to, 1L, 1);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
get_mode(mode)
|
||||
register int mode;
|
||||
{
|
||||
static char mode_buf[11];
|
||||
register int tmp = mode;
|
||||
int i;
|
||||
|
||||
mode_buf[9] = ' ';
|
||||
for (i = 0; i < 3; i++) {
|
||||
mode_buf[i * 3] = (tmp & S_IREAD) ? 'r' : '-';
|
||||
mode_buf[i * 3 + 1] = (tmp & S_IWRITE) ? 'w' : '-';
|
||||
mode_buf[i * 3 + 2] = (tmp & S_IEXEC) ? 'x' : '-';
|
||||
tmp <<= 3;
|
||||
}
|
||||
if (mode & S_ISUID)
|
||||
mode_buf[2] = 's';
|
||||
if (mode & S_ISGID)
|
||||
mode_buf[5] = 's';
|
||||
return mode_buf;
|
||||
}
|
||||
|
||||
wr_fatal()
|
||||
{
|
||||
error(TRUE, "write error\n");
|
||||
}
|
||||
|
||||
rd_fatal()
|
||||
{
|
||||
error(TRUE, "read error\n");
|
||||
}
|
||||
|
||||
mwrite(fd, address, bytes)
|
||||
int fd;
|
||||
register char *address;
|
||||
register int bytes;
|
||||
{
|
||||
if (write(fd, address, bytes) != bytes)
|
||||
error(TRUE, "write error\n");
|
||||
}
|
||||
|
||||
show(s, name)
|
||||
char *s, *name;
|
||||
{
|
||||
MEMBER x;
|
||||
char buf[sizeof(x.ar_name)+1];
|
||||
register char *p = buf, *q = name;
|
||||
|
||||
while (q <= &name[sizeof(x.ar_name)-1] && *q) *p++ = *q++;
|
||||
*p++ = '\0';
|
||||
print(s, buf);
|
||||
}
|
||||
|
||||
#ifdef AAL
|
||||
/*
|
||||
* Write out the ranlib table: first 4 bytes telling how many ranlib structs
|
||||
* there are, followed by the ranlib structs,
|
||||
* then 4 bytes giving the size of the string table, followed by the string
|
||||
* table itself.
|
||||
*/
|
||||
write_symdef()
|
||||
{
|
||||
register struct ranlib *ran;
|
||||
register int i;
|
||||
register long delta;
|
||||
MEMBER arbuf;
|
||||
|
||||
if (! tnum) return;
|
||||
if (odd(tssiz))
|
||||
tstrtab[tssiz++] = '\0';
|
||||
for (i = 0; i < sizeof(arbuf.ar_name); i++)
|
||||
arbuf.ar_name[i] = '\0';
|
||||
strcpy(arbuf.ar_name, SYMDEF);
|
||||
arbuf.ar_size = 4 + 2 * 4 * (long)tnum + 4 + (long)tssiz;
|
||||
time(&arbuf.ar_date);
|
||||
arbuf.ar_uid = getuid();
|
||||
arbuf.ar_gid = getgid();
|
||||
arbuf.ar_mode = 0444;
|
||||
#ifdef DISTRIBUTION
|
||||
if (distr_fl) {
|
||||
arbuf.ar_uid = 2;
|
||||
arbuf.ar_gid = 2;
|
||||
arbuf.ar_date = distr_time;
|
||||
}
|
||||
#endif
|
||||
wr_arhdr(ar_fd,&arbuf);
|
||||
wr_long(ar_fd, (long) tnum);
|
||||
/*
|
||||
* Account for the space occupied by the magic number
|
||||
* and the ranlib table.
|
||||
*/
|
||||
delta = 2 + AR_TOTAL + arbuf.ar_size;
|
||||
for (ran = tab; ran < &tab[tnum]; ran++) {
|
||||
ran->ran_pos += delta;
|
||||
}
|
||||
|
||||
wr_ranlib(ar_fd, tab, (long) tnum);
|
||||
wr_long(ar_fd, (long) tssiz);
|
||||
wr_bytes(ar_fd, tstrtab, (long) tssiz);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return whether the bytes in `buf' form a good object header.
|
||||
* The header is put in `headp'.
|
||||
*/
|
||||
int
|
||||
is_outhead(headp)
|
||||
register struct outhead *headp;
|
||||
{
|
||||
|
||||
return !BADMAGIC(*headp) && headp->oh_nname != 0;
|
||||
}
|
||||
|
||||
do_object(f, size)
|
||||
long size;
|
||||
{
|
||||
struct outhead headbuf;
|
||||
|
||||
if (size < SZ_HEAD) {
|
||||
/* It can't be an object file. */
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Read a header to see if it is an object file.
|
||||
*/
|
||||
if (! rd_fdopen(f)) {
|
||||
rd_fatal();
|
||||
}
|
||||
rd_ohead(&headbuf);
|
||||
if (!is_outhead(&headbuf)) {
|
||||
return;
|
||||
}
|
||||
do_names(&headbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* First skip the names and read in the string table, then seek back to the
|
||||
* name table and read and write the names one by one. Update the ranlib table
|
||||
* accordingly.
|
||||
*/
|
||||
do_names(headp)
|
||||
struct outhead *headp;
|
||||
{
|
||||
register char *strings;
|
||||
register int nnames = headp->oh_nname;
|
||||
#define NNAMES 100
|
||||
struct outname namebuf[NNAMES];
|
||||
long xxx = OFF_CHAR(*headp);
|
||||
|
||||
if ( headp->oh_nchar != (unsigned int)headp->oh_nchar ||
|
||||
(strings = malloc((unsigned int)headp->oh_nchar)) == (char *)0
|
||||
) {
|
||||
error(TRUE, "string table too big\n");
|
||||
}
|
||||
rd_string(strings, headp->oh_nchar);
|
||||
while (nnames) {
|
||||
int i = nnames >= NNAMES ? NNAMES : nnames;
|
||||
register struct outname *p = namebuf;
|
||||
|
||||
nnames -= i;
|
||||
rd_name(namebuf, i);
|
||||
while (i--) {
|
||||
long off = p->on_foff - xxx;
|
||||
if (p->on_foff == (long)0) {
|
||||
p++;
|
||||
continue; /* An unrecognizable name. */
|
||||
}
|
||||
p->on_mptr = strings + off;
|
||||
/*
|
||||
* Only enter names that are exported and are really
|
||||
* defined. Also enter common names. Note, that
|
||||
* this might cause problems when the name is really
|
||||
* defined in a later file, with a value != 0.
|
||||
* However, this problem also exists on the Unix
|
||||
* ranlib archives.
|
||||
*/
|
||||
if ( (p->on_type & S_EXT) &&
|
||||
(p->on_type & S_TYP) != S_UND
|
||||
)
|
||||
enter_name(p);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
free(strings);
|
||||
}
|
||||
|
||||
enter_name(namep)
|
||||
struct outname *namep;
|
||||
{
|
||||
register char *cp;
|
||||
|
||||
if (tnum >= tabsz) {
|
||||
tab = (struct ranlib *)
|
||||
realloc((char *) tab, (tabsz += 512) * sizeof(struct ranlib));
|
||||
if (! tab) error(TRUE, "Out of core\n");
|
||||
}
|
||||
tab[tnum].ran_off = tssiz;
|
||||
tab[tnum].ran_pos = offset;
|
||||
|
||||
for (cp = namep->on_mptr;; cp++) {
|
||||
if (tssiz >= strtabsz) {
|
||||
tstrtab = realloc(tstrtab, (strtabsz += 4096));
|
||||
if (! tstrtab) error(TRUE, "string table overflow\n");
|
||||
}
|
||||
tstrtab[tssiz++] = *cp;
|
||||
if (!*cp) break;
|
||||
}
|
||||
tnum++;
|
||||
}
|
||||
#endif /* AAL */
|
||||
@@ -1,62 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
#PARAMS do not remove this line!
|
||||
|
||||
SRC_DIR = $(SRC_HOME)/util/arch
|
||||
EMH = $(TARGET_HOME)/h
|
||||
EMBIN = $(TARGET_HOME)/bin
|
||||
LIB = $(TARGET_HOME)/modules/lib
|
||||
ULIB = $(UTIL_HOME)/modules/lib
|
||||
|
||||
LIBS = $(LIB)/libobject.$(LIBSUF) $(LIB)/libprint.$(LIBSUF) \
|
||||
$(LIB)/libstring.$(LIBSUF) $(LIB)/libsystem.$(LIBSUF)
|
||||
LINTLIBS = \
|
||||
$(ULIB)/$(LINTPREF)object.$(LINTSUF) \
|
||||
$(ULIB)/$(LINTPREF)print.$(LINTSUF) \
|
||||
$(ULIB)/$(LINTPREF)string.$(LINTSUF) \
|
||||
$(ULIB)/$(LINTPREF)system.$(LINTSUF)
|
||||
|
||||
INCLUDES = -I$(EMH)
|
||||
CFLAGS= $(INCLUDES) -DDISTRIBUTION $(COPTIONS)
|
||||
LDFLAGS = $(LDOPTIONS)
|
||||
LINTFLAGS= $(INCLUDES) -DDISTRIBUTION $(LINTOPTIONS)
|
||||
|
||||
all: arch aal
|
||||
|
||||
arch: arch.$(SUF)
|
||||
$(CC) $(LDFLAGS) -o arch arch.$(SUF) $(LIBS)
|
||||
|
||||
aal: aal.$(SUF)
|
||||
$(CC) $(LDFLAGS) -o aal aal.$(SUF) $(LIBS)
|
||||
|
||||
arch.$(SUF): $(EMH)/arch.h $(SRC_DIR)/archiver.c
|
||||
$(CC) $(CFLAGS) -c $(SRC_DIR)/archiver.c
|
||||
mv archiver.$(SUF) arch.$(SUF)
|
||||
|
||||
aal.$(SUF): $(EMH)/arch.h $(SRC_DIR)/archiver.c $(EMH)/ranlib.h $(EMH)/out.h
|
||||
$(CC) -DAAL $(CFLAGS) -c $(SRC_DIR)/archiver.c
|
||||
mv archiver.$(SUF) aal.$(SUF)
|
||||
|
||||
clean:
|
||||
rm -f aal arch *.$(SUF) *.old
|
||||
|
||||
lint:
|
||||
$(LINT) $(LINTFLAGS) -DAAL $(SRC_DIR)/archiver.c $(LINTLIBS)
|
||||
|
||||
install : all
|
||||
cp aal $(EMBIN)/aal
|
||||
cp arch $(EMBIN)/arch
|
||||
if [ $(DO_MACHINE_INDEP) = y ] ; \
|
||||
then mk_manpage $(SRC_DIR)/aal.1 $(TARGET_HOME) ; \
|
||||
mk_manpage $(SRC_DIR)/arch.1 $(TARGET_HOME) ; \
|
||||
mk_manpage $(SRC_DIR)/arch.5 $(TARGET_HOME) ; \
|
||||
fi
|
||||
|
||||
cmp : all
|
||||
-cmp aal $(EMBIN)/aal
|
||||
-cmp arch $(EMBIN)/arch
|
||||
|
||||
opr:
|
||||
make pr ^ opr
|
||||
pr:
|
||||
@pr $(SRC_DIR)/proto.make $(SRC_DIR)/archiver.c
|
||||
@@ -1,17 +0,0 @@
|
||||
proto.make
|
||||
ass00.c
|
||||
ass00.h
|
||||
ass30.c
|
||||
ass40.c
|
||||
ass50.c
|
||||
ass60.c
|
||||
ass70.c
|
||||
ass80.c
|
||||
assci.c
|
||||
asscm.c
|
||||
assda.c
|
||||
assex.h
|
||||
assrl.c
|
||||
maktab.c
|
||||
asprint.p
|
||||
em_ass.6
|
||||
@@ -1,76 +0,0 @@
|
||||
# $Header$
|
||||
d=../..
|
||||
l=$d/lib
|
||||
h=$d/h
|
||||
m=$d/man
|
||||
ASS_PATH=$l/em_ass
|
||||
|
||||
CFLAGS=-O -I$d/h
|
||||
|
||||
all: ass
|
||||
|
||||
clean:
|
||||
-rm -f ass *.o maktab *.old asstb.c
|
||||
|
||||
install : all
|
||||
rm -f $(ASS_PATH)
|
||||
cp ass $(ASS_PATH)
|
||||
rm -f $m/em_ass.6
|
||||
cp em_ass.6 $m/em_ass.6
|
||||
|
||||
cmp : all
|
||||
-cmp ass $(ASS_PATH)
|
||||
-cmp em_ass.6 $m/em_ass.6
|
||||
|
||||
lint: ass00.c ass30.c ass40.c ass50.c ass60.c ass70.c \
|
||||
ass80.c assci.c assda.c assrl.c asstb.c asscm.c
|
||||
lint -hpvbx \
|
||||
ass00.c ass30.c ass40.c ass50.c ass60.c ass70.c \
|
||||
ass80.c assci.c assda.c assrl.c asstb.c asscm.c
|
||||
|
||||
|
||||
ass: ass00.o ass30.o ass40.o ass50.o ass60.o ass70.o \
|
||||
ass80.o assci.o assda.o assrl.o asstb.o asscm.o \
|
||||
$l/em_data.a
|
||||
$(CC) $(CFLAGS) -o ass \
|
||||
ass00.o ass30.o ass40.o ass50.o ass60.o ass70.o \
|
||||
ass80.o assci.o assda.o assrl.o asstb.o asscm.o \
|
||||
$l/em_data.a
|
||||
|
||||
ass00.o ass40.o ass60.o ass70.o ass80.o assrl.o: \
|
||||
$h/local.h $h/em_spec.h $h/as_spec.h \
|
||||
$h/em_flag.h $h/arch.h ass00.h assex.h
|
||||
|
||||
assci.o: $h/local.h $h/em_spec.h $h/as_spec.h \
|
||||
$h/em_flag.h $h/em_mes.h $h/em_pseu.h \
|
||||
$h/em_ptyp.h $h/arch.h ass00.h assex.h
|
||||
|
||||
ass30.o ass50.o : \
|
||||
$h/local.h $h/em_spec.h $h/as_spec.h \
|
||||
$h/em_flag.h ip_spec.h ass00.h assex.h
|
||||
|
||||
ass80.o: $h/em_path.h
|
||||
|
||||
assda.o: $h/local.h $h/em_spec.h $h/as_spec.h \
|
||||
$h/em_flag.h $h/arch.h ass00.h
|
||||
|
||||
asscm.o: ass00.h
|
||||
|
||||
asstb.o: asstb.c
|
||||
|
||||
asstb.c: maktab $d/etc/ip_spec.t
|
||||
maktab $d/etc/ip_spec.t asstb.c
|
||||
|
||||
maktab: maktab.c $h/em_spec.h ip_spec.h $h/em_flag.h \
|
||||
$l/em_data.a
|
||||
$(CC) -O -o maktab maktab.c $l/em_data.a
|
||||
|
||||
asprint: asprint.p
|
||||
apc -w -o asprint asprint.p
|
||||
|
||||
opr:
|
||||
make pr ^ opr
|
||||
|
||||
pr:
|
||||
@(pr ass00.h assex.h ip_spec.h ass?0.c ass[rcd]?.c \
|
||||
maktab.c)
|
||||
@@ -1,2 +0,0 @@
|
||||
- make the tables that still have a fixed length of dynamically varying
|
||||
length, and remove the size options
|
||||
@@ -1,386 +0,0 @@
|
||||
#
|
||||
{$d+}
|
||||
program asprint(prog,output);
|
||||
|
||||
const
|
||||
|
||||
{ header words }
|
||||
NTEXT = 1;
|
||||
NDATA = 2;
|
||||
NPROC = 3;
|
||||
ENTRY = 4;
|
||||
NLINE = 5;
|
||||
SZDATA = 6;
|
||||
|
||||
escape1 = 254; { escape to secondary opcodes }
|
||||
escape2 = 255; { escape to tertiary opcodes }
|
||||
|
||||
type
|
||||
byte= 0..255; { memory is an array of bytes }
|
||||
adr= {0..maxadr} long; { the range of addresses }
|
||||
word= {0..maxuint} long;{ the range of unsigned integers }
|
||||
size= 0..32766; { the range of sizes is the positive offsets }
|
||||
sword= {-signbit..maxsint} long; { the range of signed integers }
|
||||
full= {-maxuint..maxuint} long; { intermediate results need this range }
|
||||
double={-maxdbl..maxdbl} long; { double precision range }
|
||||
insclass=(prim,second,tert); { tells which opcode table is in use }
|
||||
instype=(implic,explic); { does opcode have implicit or explicit operand }
|
||||
iflags= (mini,short,sbit,wbit,zbit,ibit);
|
||||
ifset= set of iflags;
|
||||
|
||||
mnem = ( NON,
|
||||
AAR, ADF, ADI, ADP, ADS, ADU,XAND, ASP, ASS, BEQ,
|
||||
BGE, BGT, BLE, BLM, BLS, BLT, BNE, BRA, CAI, CAL,
|
||||
CFF, CFI, CFU, CIF, CII, CIU, CMF, CMI, CMP, CMS,
|
||||
CMU, COM, CSA, CSB, CUF, CUI, CUU, DCH, DEC, DEE,
|
||||
DEL, DUP, DUS, DVF, DVI, DVU, EXG, FEF, FIF, FIL,
|
||||
GTO, INC, INE, INL, INN, IOR, LAE, LAL, LAR, LDC,
|
||||
LDE, LDF, LDL, LFR, LIL, LIM, LIN, LNI, LOC, LOE,
|
||||
LOF, LOI, LOL, LOR, LOS, LPB, LPI, LXA, LXL, MLF,
|
||||
MLI, MLU, MON, NGF, NGI, NOP, RCK, RET, RMI, RMU,
|
||||
ROL, ROR, RTT, SAR, SBF, SBI, SBS, SBU, SDE, SDF,
|
||||
SDL,XSET, SIG, SIL, SIM, SLI, SLU, SRI, SRU, STE,
|
||||
STF, STI, STL, STR, STS, TEQ, TGE, TGT, TLE, TLT,
|
||||
TNE, TRP, XOR, ZEQ, ZER, ZGE, ZGT, ZLE, ZLT, ZNE,
|
||||
ZRE, ZRF, ZRL);
|
||||
|
||||
dispatch = record
|
||||
iflag: ifset;
|
||||
instr: mnem;
|
||||
case instype of
|
||||
implic: (implicit:sword);
|
||||
explic: (ilength:byte);
|
||||
end;
|
||||
|
||||
var
|
||||
{ variables indicating the size of words and addresses }
|
||||
wsize: integer; { number of bytes in a word }
|
||||
asize: integer; { number of bytes in an address }
|
||||
pdsize: integer; { size of procedure descriptor in bytes = 2*asize }
|
||||
|
||||
pc,lb,sp,hp,pd: adr; { internal machine registers }
|
||||
i: integer; { integer scratch variable }
|
||||
s,t :word; { scratch variables }
|
||||
sz:size; { scratch variables }
|
||||
ss,st: sword; { scratch variables }
|
||||
k :double; { scratch variables }
|
||||
j:size; { scratch variable used as index }
|
||||
a,b:adr; { scratch variable used for addresses }
|
||||
dt,ds:double; { scratch variables for double precision }
|
||||
found:boolean; { scratch }
|
||||
opcode: byte;
|
||||
iclass: insclass;
|
||||
dispat: array[insclass, byte] of dispatch ;
|
||||
insr: mnem; { holds the instructionnumber }
|
||||
header: array[1..8] of adr;
|
||||
|
||||
prog: file of byte; { program and initialized data }
|
||||
|
||||
procedure getit; { start the ball rolling }
|
||||
var cset:set of char;
|
||||
f:ifset;
|
||||
insno:byte;
|
||||
iclass: insclass;
|
||||
nops:integer;
|
||||
opcode:byte;
|
||||
i,j,n:integer;
|
||||
wtemp:sword;
|
||||
count:integer;
|
||||
repc:adr;
|
||||
nexta,firsta:adr;
|
||||
elem:byte;
|
||||
amount,ofst:size;
|
||||
c:char;
|
||||
|
||||
function readb(n:integer):double;
|
||||
var b:byte;
|
||||
begin
|
||||
if eof(prog) then
|
||||
begin writeln('Premature EOF on EM load file') ; halt end;
|
||||
read(prog,b); if n>1 then readb:=readb(n-1)*256+b else readb:=b
|
||||
end;
|
||||
|
||||
function readbyte:byte;
|
||||
begin readbyte:=readb(1) end;
|
||||
|
||||
procedure skipbyte;
|
||||
var dummy: byte;
|
||||
begin dummy:=readb(1) end;
|
||||
|
||||
function readword:word;
|
||||
begin readword:=readb(wsize) end;
|
||||
|
||||
function readadr:adr;
|
||||
begin readadr:=readb(asize) end;
|
||||
|
||||
function ifind(ordinal:byte):mnem;
|
||||
var loopvar:mnem;
|
||||
found:boolean;
|
||||
begin ifind:=NON;
|
||||
loopvar:=insr; found:=false;
|
||||
repeat
|
||||
if ordinal=ord(loopvar) then
|
||||
begin found:=true; ifind:=loopvar end;
|
||||
if loopvar<>ZRL then loopvar:=succ(loopvar) else loopvar:=NON;
|
||||
until found or (loopvar=insr) ;
|
||||
end;
|
||||
|
||||
procedure readhdr;
|
||||
type hdrw=0..32767 ; { 16 bit header words }
|
||||
var hdr: hdrw;
|
||||
i: integer;
|
||||
begin
|
||||
for i:=0 to 7 do
|
||||
begin hdr:=readb(2);
|
||||
case i of
|
||||
0: if hdr<>3757 then { 07255 }
|
||||
begin writeln('Not an em load file'); halt end;
|
||||
1: writeln('Test flags: ',hdr);
|
||||
2: if hdr<>0 then
|
||||
begin writeln('Unsolved references: ',hdr) end;
|
||||
3: if hdr<>3 then
|
||||
begin writeln('Incorrect load file version') end;
|
||||
4: wsize:=hdr ;
|
||||
5: begin asize:=hdr ; pdsize:= asize+asize end;
|
||||
6,7:
|
||||
if hdr<>0 then
|
||||
begin writeln('First header entry ',i,', is ',hdr) end;
|
||||
end
|
||||
end;
|
||||
writeln('word size',wsize,', pointer size',asize)
|
||||
end;
|
||||
|
||||
procedure noinit;
|
||||
begin writeln('Illegal initialization'); halt end;
|
||||
|
||||
procedure readint(a:adr;s:size);
|
||||
const mrange = 4;
|
||||
var i:size;
|
||||
val:double;
|
||||
cont: array[1..mrange] of byte;
|
||||
begin { construct integer out of byte sequence }
|
||||
if s<=mrange then
|
||||
begin
|
||||
for i:=1 to s do cont[i]:=readbyte ;
|
||||
if cont[s]>=128 then val:=cont[s]-256 else val:=cont[s];
|
||||
for i:= s-1 downto 1 do val:= val*256 + cont[i];
|
||||
writeln(', value ',val)
|
||||
end
|
||||
else
|
||||
begin
|
||||
write(', bytes(little endian) ');
|
||||
for i:=1 to s do write(readbyte:4) ;
|
||||
writeln
|
||||
end
|
||||
end;
|
||||
|
||||
procedure readuns(a:adr;s:size);
|
||||
const mrange=3;
|
||||
var i:size;
|
||||
val:double;
|
||||
cont: array[1..mrange] of byte;
|
||||
begin { construct unsigned integer out of byte sequence }
|
||||
if s<=mrange then
|
||||
begin
|
||||
for i:=1 to s do cont[i]:=readbyte ;
|
||||
val:=0;
|
||||
for i:= s downto 1 do val:= val*256 + cont[i];
|
||||
writeln(', value ',val)
|
||||
end
|
||||
else
|
||||
begin
|
||||
write(', bytes(little endian) ');
|
||||
for i:=1 to s do write(readbyte:4) ;
|
||||
writeln
|
||||
end
|
||||
end;
|
||||
|
||||
procedure readfloat(a:adr;s:size);
|
||||
var i:size; b:byte;
|
||||
begin { construct float out of string}
|
||||
i:=0;
|
||||
repeat { eat the bytes, construct the value and intialize at a }
|
||||
write(chr(readbyte)); i:=i+1;
|
||||
until b=0 ;
|
||||
end;
|
||||
|
||||
begin
|
||||
|
||||
#ifdef INSRT
|
||||
{ initialize tables }
|
||||
for iclass:=prim to tert do
|
||||
for i:=0 to 255 do
|
||||
with dispat[iclass][i] do
|
||||
begin instr:=NON; iflag:=[zbit] end;
|
||||
|
||||
{ read instruction table file. see appendix B }
|
||||
{ The table read here is a simple transformation of the table on page xx }
|
||||
{ - instruction names were transformed to numbers }
|
||||
{ - the '-' flag was transformed to an 'i' flag for 'w' type instructions }
|
||||
{ - the 'S' flag was added for instructions having signed operands }
|
||||
reset(tables);
|
||||
insr:=NON;
|
||||
repeat
|
||||
read(tables,insno) ; cset:=[]; f:=[];
|
||||
insr:=ifind(insno);
|
||||
if insr=NON then begin writeln('Incorrect table'); halt end;
|
||||
repeat read(tables,c) until c<>' ' ;
|
||||
repeat
|
||||
cset:=cset+[c];
|
||||
read(tables,c)
|
||||
until c=' ' ;
|
||||
if 'm' in cset then f:=f+[mini];
|
||||
if 's' in cset then f:=f+[short];
|
||||
if '-' in cset then f:=f+[zbit];
|
||||
if 'i' in cset then f:=f+[ibit];
|
||||
if 'S' in cset then f:=f+[sbit];
|
||||
if 'w' in cset then f:=f+[wbit];
|
||||
if (mini in f) or (short in f) then read(tables,nops) else nops:=1 ;
|
||||
readln(tables,opcode);
|
||||
if ('4' in cset) or ('8' in cset) then
|
||||
begin iclass:=tert end
|
||||
else if 'e' in cset then
|
||||
begin iclass:=second end
|
||||
else iclass:=prim;
|
||||
for i:=0 to nops-1 do
|
||||
begin
|
||||
with dispat[iclass,opcode+i] do
|
||||
begin
|
||||
iflag:=f; instr:=insr;
|
||||
if '2' in cset then ilength:=2
|
||||
else if 'u' in cset then ilength:=2
|
||||
else if '4' in cset then ilength:=4
|
||||
else if '8' in cset then ilength:=8
|
||||
else if (mini in f) or (short in f) then
|
||||
begin
|
||||
if 'N' in cset then wtemp:=-1-i else wtemp:=i ;
|
||||
if 'o' in cset then wtemp:=wtemp+1 ;
|
||||
if short in f then wtemp:=wtemp*256 ;
|
||||
implicit:=wtemp
|
||||
end
|
||||
end
|
||||
end
|
||||
until eof(tables);
|
||||
|
||||
#endif
|
||||
{ read in program text, data and procedure descriptors }
|
||||
reset(prog);
|
||||
readhdr; { verify first header }
|
||||
for i:=1 to 8 do header[i]:=readadr; { read second header }
|
||||
writeln('textsize ',header[NTEXT],', datasize ',header[SZDATA]);
|
||||
writeln('data descriptors: ',header[NDATA]);
|
||||
writeln('procedure descriptors: ',header[NPROC]);
|
||||
writeln('entry procedure: ',header[ENTRY]);
|
||||
if header[7]<>0 then writeln('Second header entry 7 is ',header[7]);
|
||||
if header[8]<>0 then writeln('Second header entry 8 is ',header[8]);
|
||||
{ read program text }
|
||||
for i:=0 to header[NTEXT]-1 do skipbyte;
|
||||
{ read data blocks }
|
||||
writeln; writeln('Data descriptors:');
|
||||
nexta:=0;
|
||||
for i:=1 to header[NDATA] do
|
||||
begin
|
||||
n:=readbyte;
|
||||
write(nexta:5,'- ');
|
||||
if n<>0 then
|
||||
begin
|
||||
elem:=readbyte; firsta:=nexta;
|
||||
case n of
|
||||
1: { uninitialized words }
|
||||
begin
|
||||
writeln(elem,' uninitialised word(s)');
|
||||
nexta:= nexta+ elem*wsize ;
|
||||
end;
|
||||
2: { initialized bytes }
|
||||
begin
|
||||
write(elem,' initialised byte(s)');
|
||||
for j:=1 to elem do
|
||||
begin
|
||||
if j mod 10 = 1 then
|
||||
begin writeln ; write(nexta:6,':') end ;
|
||||
write(readbyte:4); nexta:=nexta+1
|
||||
end;
|
||||
writeln
|
||||
end;
|
||||
3: { initialized words }
|
||||
begin
|
||||
write(elem,' initialised word(s)');
|
||||
for j:=1 to elem do
|
||||
begin
|
||||
if j mod 8 = 1 then
|
||||
begin writeln ; write(nexta:6,':') end ;
|
||||
write(readword:9); nexta:=nexta+wsize
|
||||
end;
|
||||
writeln
|
||||
end;
|
||||
4,5: { instruction and data pointers }
|
||||
begin
|
||||
if n=4 then
|
||||
write(elem,' initialised data pointers')
|
||||
else
|
||||
write(elem,' initialised instruction pointers');
|
||||
for j:=1 to elem do
|
||||
begin
|
||||
if j mod 8 = 1 then
|
||||
begin writeln ; write(nexta:6,':') end ;
|
||||
write(readadr:9); nexta:=nexta+asize
|
||||
end;
|
||||
writeln
|
||||
end;
|
||||
6: { signed integers }
|
||||
begin
|
||||
write(elem,'-byte signed integer ');
|
||||
readint(nexta,elem); nexta:=nexta+elem
|
||||
end;
|
||||
7: { unsigned integers }
|
||||
begin
|
||||
write(elem,'-byte unsigned integer ');
|
||||
readuns(nexta,elem); nexta:=nexta+elem
|
||||
end;
|
||||
8: { floating point numbers }
|
||||
begin
|
||||
write(elem,'-byte floating point number ');
|
||||
readfloat(nexta,elem); nexta:=nexta+elem
|
||||
end;
|
||||
end
|
||||
end
|
||||
else
|
||||
begin
|
||||
repc:=readadr;
|
||||
amount:=nexta-firsta;
|
||||
writeln(repc,' copies of the data from ',firsta:2,' to ',nexta:2);
|
||||
nexta:= nexta + repc*amount ;
|
||||
end
|
||||
end;
|
||||
if header[SZDATA]<>nexta then writeln('Data initialization error');
|
||||
{ read descriptor table }
|
||||
pd:=header[NTEXT];
|
||||
for i:=1 to header[NPROC]*pdsize do skipbyte;
|
||||
end;
|
||||
|
||||
begin getit;
|
||||
#ifdef RTC
|
||||
repeat
|
||||
opcode := nextpc; { fetch the first byte of the instruction }
|
||||
if opcode=escape1 then iclass:=second
|
||||
else if opcode=escape2 then iclass:=tert
|
||||
else iclass:=prim;
|
||||
if iclass<>prim then opcode := nextpc;
|
||||
with dispat[iclass][opcode] do
|
||||
begin insr:=instr;
|
||||
if not (zbit in iflag) then
|
||||
if ibit in iflag then k:=pop else
|
||||
begin
|
||||
if mini in iflag then k:=implicit else
|
||||
begin
|
||||
if short in iflag then k:=implicit+nextpc else
|
||||
begin k:=nextpc;
|
||||
if (sbit in iflag) and (k>=128) then k:=k-256;
|
||||
for i:=2 to ilength do k:=256*k + nextpc
|
||||
end
|
||||
end;
|
||||
if wbit in iflag then k:=k*wsize;
|
||||
end
|
||||
end;
|
||||
#endif
|
||||
end.
|
||||
528
util/ass/ass00.c
528
util/ass/ass00.c
@@ -1,528 +0,0 @@
|
||||
#include "ass00.h"
|
||||
#include "assex.h"
|
||||
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Main routine of EM1-assembler/loader
|
||||
*/
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
/*
|
||||
* Usage: ass [-[d][p][m][u][U]] [-s(s/m/l/x)] [ [file] [flag] ] ...
|
||||
* The d flag can be repeated several times, resulting in more
|
||||
* debugging information.
|
||||
*/
|
||||
char workspace[6000] ;
|
||||
register char *cp ;
|
||||
register int argno ;
|
||||
|
||||
progname = argv[0];
|
||||
for ( cp=argv[0] ; *cp ; ) if ( *cp++ == '/' ) progname= cp;
|
||||
for ( argno=1 ; argno<argc ; argno++ ) {
|
||||
if ( argv[argno][0] == '-' && LC(argv[argno][1]) == 's') {
|
||||
getsizes(&argv[argno][2]);
|
||||
break ;
|
||||
}
|
||||
}
|
||||
/* A piece of the interpreter's stack frame is used as
|
||||
free area initially */
|
||||
freearea( (area_t) workspace, (unsigned) sizeof workspace ) ;
|
||||
getcore();
|
||||
init_files();
|
||||
init_vars();
|
||||
while ( --argc )
|
||||
argument(*++argv);
|
||||
finish_up();
|
||||
exit(nerrors!=0);
|
||||
}
|
||||
|
||||
getcore() {
|
||||
register siz_t *p;
|
||||
siz_t bytes;
|
||||
register unsigned n ;
|
||||
register char *base ;
|
||||
|
||||
/*
|
||||
* xglobs[] should be located in front of mglobs[], see upd_reloc()
|
||||
*/
|
||||
|
||||
p = oursize; n = 0;
|
||||
n += (bytes.n_glab = p->n_glab * (sizeof *xglobs));
|
||||
n += (bytes.n_mlab = p->n_mlab * (sizeof *mglobs));
|
||||
n += (bytes.n_mproc = p->n_mproc * (sizeof *mprocs));
|
||||
n += (bytes.n_xproc = p->n_xproc * (sizeof *xprocs));
|
||||
n += (bytes.n_proc = p->n_proc * (sizeof *proctab));
|
||||
base = getarea(n);
|
||||
zero(base,n);
|
||||
xglobs = gbp_cast base; base += bytes.n_glab;
|
||||
mglobs = gbp_cast base; base += bytes.n_mlab;
|
||||
mprocs = prp_cast base; base += bytes.n_mproc;
|
||||
xprocs = prp_cast base; base += bytes.n_xproc;
|
||||
proctab = ptp_cast base; base += bytes.n_proc;
|
||||
}
|
||||
|
||||
getsizes(str) char *str; {
|
||||
|
||||
/*
|
||||
* accepts -ss (small), -sm (medium), -sl (large), -sx (extra large)
|
||||
*/
|
||||
|
||||
switch(LC(*str)) {
|
||||
default:error("bad size option %s",str);
|
||||
case 's': oursize = &sizes[0]; break;
|
||||
case 'm': oursize = &sizes[1]; break;
|
||||
case 'l': oursize = &sizes[2]; break;
|
||||
case 'x': oursize = &sizes[3]; break;
|
||||
}
|
||||
}
|
||||
|
||||
char oflag;
|
||||
|
||||
argument(arg) char *arg; {
|
||||
register w;
|
||||
|
||||
/*
|
||||
* This routine decides what to do with each argument.
|
||||
* It recognises flags and modules.
|
||||
* Furthermore, it knows a library when it sees it and
|
||||
* call archive() to split it apart.
|
||||
*/
|
||||
|
||||
if (oflag) {
|
||||
eout = arg;
|
||||
oflag=0;
|
||||
return;
|
||||
}
|
||||
if(*arg == '-') {
|
||||
flags(arg);
|
||||
return;
|
||||
}
|
||||
curfile = arg; /* for error messages etc. */
|
||||
if ((ifile = fopen(arg,"r")) == 0) {
|
||||
error("can't open %s",arg);
|
||||
return;
|
||||
}
|
||||
inpoff = 2;
|
||||
if ((w = getu16()) == sp_magic )
|
||||
read_compact();
|
||||
else if (w == ARMAG || w == AALMAG) {
|
||||
archmode = TRUE;
|
||||
archive();
|
||||
archmode = FALSE;
|
||||
} else
|
||||
error("%s: bad format",arg);
|
||||
if (fclose(ifile) == EOF)
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
** process flag arguments
|
||||
*/
|
||||
|
||||
static int memflg ;
|
||||
|
||||
flags(arg)
|
||||
char *arg;
|
||||
{
|
||||
register char *argp;
|
||||
register on;
|
||||
|
||||
argp = arg;
|
||||
while (*++argp)
|
||||
{
|
||||
switch(LC(*argp))
|
||||
{
|
||||
case 'd': d_flag++;break;
|
||||
case 'r': r_flag++;break;
|
||||
case 's': return ; /* s-flag is already scanned */
|
||||
#ifdef MEMUSE
|
||||
case 'm': memflg++ ; break ;
|
||||
#endif
|
||||
case 'p': ++procflag;break;
|
||||
#ifdef DUMP
|
||||
case 'u': ++c_flag;break;
|
||||
#endif
|
||||
case 'o': ++oflag; break;
|
||||
case 'w': ++wflag; break;
|
||||
#ifdef JOHAN
|
||||
case 'j': ++jflag; break;
|
||||
#endif
|
||||
case 'U': ++Uflag; break;
|
||||
case '-':
|
||||
case '+':
|
||||
on = (*argp == '+');
|
||||
while (*++argp) switch(LC(*argp)) {
|
||||
case 't': if (on) intflags |= 01;
|
||||
else intflags &= ~01;
|
||||
break;
|
||||
case 'p': if (on) intflags |= 02;
|
||||
else intflags &= ~02;
|
||||
break;
|
||||
case 'f': if (on) intflags |= 04;
|
||||
else intflags &= ~04;
|
||||
break;
|
||||
case 'c': if (on) intflags |= 010;
|
||||
else intflags &= ~010;
|
||||
case 'e': if (on) intflags |= 040;
|
||||
else intflags &= ~040;
|
||||
break;
|
||||
default:
|
||||
error("bad interpreter option %s",argp);
|
||||
}
|
||||
--argp;
|
||||
break;
|
||||
default:
|
||||
error("bad flag %s",argp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
do_proc() {
|
||||
/* One procedure has been read and will be processed.
|
||||
*
|
||||
* NOTE: The numbers of the passes, 1 3 4 and 5, are a remainder
|
||||
* of ancient times.
|
||||
*/
|
||||
|
||||
dump(1); if ( memflg>2 )memuse();
|
||||
pass_3(); dump(3);
|
||||
pass_4(); dump(4);
|
||||
pass_5(); if ( memflg>2 ) memuse() ;
|
||||
endproc(); if ( memflg>1 ) memuse() ;
|
||||
}
|
||||
|
||||
archive() {
|
||||
register i;
|
||||
register char *p;
|
||||
|
||||
/*
|
||||
* Read a library.
|
||||
* The format of the libary used is that of a UNIX/V7(PDP)-archive.
|
||||
*
|
||||
* NOTE: If it was allowed for an archive to contain
|
||||
* obligatory modules as well as optionals,
|
||||
* it would not be possible to speed up things a bit
|
||||
* by stopping when all references are resolved.
|
||||
* This is the only reason.
|
||||
*/
|
||||
|
||||
for(;;) {
|
||||
if (unresolved == 0) { /* no use for this library anymore */
|
||||
return;
|
||||
}
|
||||
p = chp_cast &archhdr;
|
||||
if ((i = fgetc(ifile))==EOF ) {
|
||||
return;
|
||||
}
|
||||
*p++ = i;
|
||||
for (i=1;i< sizeof archhdr.ar_name; i++)
|
||||
*p++ = get8();
|
||||
for (i=0;i<8;i++) get8();
|
||||
archhdr.ar_size= ((long)get16()<<16) ;
|
||||
archhdr.ar_size+= getu16();
|
||||
inpoff = 0; libeof = archhdr.ar_size;
|
||||
/*
|
||||
* UNIX archiveheader is read now, now process the contents
|
||||
* of it. Note that recursive archives are not implemented.
|
||||
*
|
||||
* The variable libeof is used by get8() to check
|
||||
* whether or not we try to pass the library-boundary.
|
||||
*/
|
||||
if ( getu16() == sp_magic ) {
|
||||
read_compact();
|
||||
} else
|
||||
error("bad archive entry");
|
||||
skipentry();
|
||||
libeof = 0;
|
||||
} /* up to the next entry */
|
||||
}
|
||||
|
||||
skipentry() {
|
||||
|
||||
/*
|
||||
* for some reason the rest of this library entry needs to be
|
||||
* skipped. Do that now.
|
||||
*/
|
||||
while(inpoff<libeof)
|
||||
get8();
|
||||
if(odd(libeof)) /* archive entries are evensized */
|
||||
if (fgetc(ifile) == EOF) /* except maybe the last one */
|
||||
;
|
||||
}
|
||||
|
||||
init_vars() {
|
||||
|
||||
/*
|
||||
* A small collection of variables is initialized.
|
||||
* This occurs only for those that couldn't be initialized
|
||||
* at compile-time.
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
init_files() {
|
||||
|
||||
/*
|
||||
* The temporary files on which text and data are kept
|
||||
* during assembly are set up here.
|
||||
*/
|
||||
#ifdef CPM
|
||||
unlink("????????.$$$");
|
||||
tfile=fopen("TFILE.$$$", "w");
|
||||
dfile=fopen("DFILE.$$$", "w");
|
||||
rtfile=fopen("RTFILE.$$$", "w");
|
||||
rdfile=fopen("RDFILE.$$$", "w");
|
||||
#else
|
||||
/*
|
||||
* The function tmpfil() returns a file-descriptor
|
||||
* of a file that is valid for reading and writing.
|
||||
* It has the nice property of generating truly unique names.
|
||||
*/
|
||||
|
||||
tfile=fdopen(tmpfil(),"w") ;
|
||||
dfile=fdopen(tmpfil(),"w") ;
|
||||
rtfile=fdopen(tmpfil(),"w") ;
|
||||
rdfile=fdopen(tmpfil(),"w") ;
|
||||
#endif
|
||||
}
|
||||
|
||||
initproc() {
|
||||
|
||||
/*
|
||||
* Called at the start of assembly of every procedure.
|
||||
*/
|
||||
|
||||
stat_t *prevstate ;
|
||||
|
||||
prevstate= pst_cast getarea(sizeof pstate) ;
|
||||
*prevstate= pstate ;
|
||||
pstate.s_prevstat= prevstate ;
|
||||
pstate.s_curpro= prp_cast 0 ;
|
||||
pstate.s_fline= lnp_cast 0 ;
|
||||
pstate.s_fdata= l_data ;
|
||||
pstate.s_locl = (locl_t (*)[])
|
||||
getarea(LOCLABSIZE * sizeof ((*(pstate.s_locl))[0]));
|
||||
zero(chp_cast pstate.s_locl,
|
||||
LOCLABSIZE * (unsigned) sizeof ((*(pstate.s_locl))[0]));
|
||||
if ( memflg>2 ) memuse() ;
|
||||
}
|
||||
|
||||
endproc() {
|
||||
/* Throw the contents of the line and local label table away */
|
||||
register line_t *lnp1;
|
||||
register locl_t *lbhead,*lbp,*lbp_next;
|
||||
register kind ;
|
||||
register stat_t *prevstate;
|
||||
|
||||
while ( lnp1= pstate.s_fline ) {
|
||||
pstate.s_fline= lnp1->l_next ;
|
||||
kind= lnp1->type1 ;
|
||||
if ( kind>VALLOW ) kind=VALLOW ;
|
||||
freearea((area_t)lnp1,(unsigned)linesize[kind]) ;
|
||||
}
|
||||
prevstate= pstate.s_prevstat ;
|
||||
if ( prevstate!= pst_cast 0 ) {
|
||||
for ( lbhead= *pstate.s_locl;
|
||||
lbhead<&(*pstate.s_locl)[LOCLABSIZE] ; lbhead++ ) {
|
||||
for ( lbp=lbhead->l_chain; lbp!= lbp_cast 0; lbp= lbp_next ) {
|
||||
lbp_next= lbp->l_chain;
|
||||
freearea((area_t)lbp,(unsigned)sizeof *lbp) ;
|
||||
}
|
||||
}
|
||||
freearea((area_t)(*pstate.s_locl),
|
||||
LOCLABSIZE * (sizeof((*pstate.s_locl)[0])));
|
||||
pstate= *prevstate ;
|
||||
freearea((area_t)prevstate,(unsigned)sizeof *prevstate) ;
|
||||
}
|
||||
}
|
||||
|
||||
init_module() {
|
||||
|
||||
/*
|
||||
* Called at the start of every module.
|
||||
*/
|
||||
|
||||
holbase = 0;
|
||||
line_num = 1;
|
||||
mod_sizes = 0;
|
||||
}
|
||||
|
||||
end_module() {
|
||||
|
||||
/*
|
||||
* Finish a module.
|
||||
* Work to be done is mainly forgetting of local names,
|
||||
* and remembering of those that will live during assembly.
|
||||
*/
|
||||
|
||||
align(wordsize) ;
|
||||
setmode(DATA_NUL);
|
||||
dump(100);
|
||||
enmd_pro();
|
||||
enmd_glo();
|
||||
if ( memflg ) memuse() ;
|
||||
}
|
||||
|
||||
enmd_pro() {
|
||||
register proc_t *p,*limit;
|
||||
|
||||
/*
|
||||
* Check that all local procedures have been defined,
|
||||
* and forget them immediately thereafter.
|
||||
*/
|
||||
|
||||
limit = &mprocs[oursize->n_mproc];
|
||||
for (p=mprocs; p<limit; p++) {
|
||||
if (p->p_name == 0)
|
||||
continue;
|
||||
if ((p->p_status&DEF)==0)
|
||||
error("undefined local procedure '%s'",p->p_name);
|
||||
}
|
||||
zero(chp_cast mprocs,(limit-mprocs)* (unsigned)sizeof *mprocs);
|
||||
|
||||
/* Clobber all flags indicating that external procedures
|
||||
* were used in this module.
|
||||
*/
|
||||
|
||||
limit = &xprocs[oursize->n_xproc];
|
||||
for (p=xprocs; p<limit; p++) {
|
||||
p->p_status &= ~EXT ;
|
||||
}
|
||||
}
|
||||
|
||||
enmd_glo() {
|
||||
register glob_t *mg,*xg,*limit;
|
||||
|
||||
/*
|
||||
* Tougher then enmd_pro().
|
||||
* Check all the symbols used in this module that are
|
||||
* not to be forgotten immediately.
|
||||
* A difficulty arises here:
|
||||
* In the tables textreloc[] and datareloc[]
|
||||
* pointers are used to identify the symbols concerned.
|
||||
* These pointers point into mglobs[].
|
||||
* Since at the end of assembly only the value of xglobs[]
|
||||
* is defined, these pointers have to be changed.
|
||||
* upd_reloc() takes care of this.
|
||||
*/
|
||||
|
||||
limit = &mglobs[oursize->n_mlab];
|
||||
for ( mg = mglobs; mg < limit; mg++) {
|
||||
if (mg->g_name == 0)
|
||||
continue;
|
||||
if ((mg->g_status&(EXT|DEF))==0)
|
||||
error("undefined local symbol '%s'",glostring(mg));
|
||||
if ((mg->g_status&EXT)==0)
|
||||
continue;
|
||||
xg = xglolookup(mg->g_name,ENTERING);
|
||||
switch(xg->g_status&(EXT|DEF)) {
|
||||
case 0: /* new symbol */
|
||||
if((mg->g_status&DEF)==0)
|
||||
++unresolved;
|
||||
break;
|
||||
case EXT: /* already used but not defined */
|
||||
if(mg->g_status&DEF) {
|
||||
--unresolved;
|
||||
}
|
||||
break;
|
||||
}
|
||||
xg->g_status |= mg->g_status;
|
||||
if (mg->g_status&DEF)
|
||||
xg->g_val.g_addr = mg->g_val.g_addr;
|
||||
else
|
||||
mg->g_val.g_gp = xg; /* used by upd_reloc */
|
||||
} /* up to the next symbol */
|
||||
upd_reloc();
|
||||
zero(chp_cast mglobs,(limit-mglobs)*(unsigned) sizeof *mglobs);
|
||||
}
|
||||
|
||||
finish_up()
|
||||
{
|
||||
/*
|
||||
* Almost done. Check for unresolved references,
|
||||
* make the e.out file and stop.
|
||||
*/
|
||||
|
||||
#ifdef DUMP
|
||||
c_print();
|
||||
#endif
|
||||
check_def();
|
||||
if ( nerrors==0 ) copyout();
|
||||
}
|
||||
|
||||
#ifdef DUMP
|
||||
c_print() {
|
||||
if ( ! c_flag ) return ;
|
||||
c_dprint("primary",opcnt1) ;
|
||||
c_dprint("secondary",opcnt2) ;
|
||||
c_dprint("extra long",opcnt3) ;
|
||||
}
|
||||
|
||||
c_dprint(str,cnt) char *str,*cnt ; {
|
||||
register int first,curr ;
|
||||
printf("unused %s opcodes\n",str) ;
|
||||
for ( first= -1 , curr=0 ; curr<=256 ; curr++ ) {
|
||||
if ( curr==256 || cnt[curr] ) {
|
||||
if ( first!= -1 ) {
|
||||
if ( first+1 == curr ) {
|
||||
printf("%3d\n",first ) ;
|
||||
} else {
|
||||
printf("%3d..%3d\n",first,curr-1) ;
|
||||
}
|
||||
first= -1 ;
|
||||
}
|
||||
} else {
|
||||
if ( first== -1 ) first=curr ;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
check_def() {
|
||||
register proc_t *p;
|
||||
register glob_t *g;
|
||||
register count;
|
||||
|
||||
/*
|
||||
* Check for unresolved references.
|
||||
* NOTE: The occurring of unresolved references is not fatal,
|
||||
* although the use of the e.out file after this
|
||||
* occurring must be strongly discouraged.
|
||||
* Every use of the symbols concerned is undefined.
|
||||
*/
|
||||
|
||||
if (unresolved) {
|
||||
printf("Unresolved references\n Procedures:\n");
|
||||
count = oursize->n_xproc;
|
||||
for (p = xprocs; count--; p++)
|
||||
if (p->p_name && (p->p_status&DEF)==0)
|
||||
printf(" %s\n",p->p_name);
|
||||
printf(" Data:\n");
|
||||
count = oursize->n_glab;
|
||||
for (g = xglobs; count--; g++)
|
||||
if (g->g_name && (g->g_status&DEF)==0)
|
||||
printf(" %s\n",glostring(g));
|
||||
if (! Uflag) nerrors++;
|
||||
}
|
||||
}
|
||||
|
||||
ertrap() { /* trap routine to drain input in case of compile errors */
|
||||
|
||||
if (fileno(ifile)== 0)
|
||||
while (fgetc(ifile) != EOF)
|
||||
;
|
||||
exit(1);
|
||||
}
|
||||
253
util/ass/ass00.h
253
util/ass/ass00.h
@@ -1,253 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <em_spec.h>
|
||||
#include <as_spec.h>
|
||||
#include <em_flag.h>
|
||||
#include <arch.h>
|
||||
#include <local.h>
|
||||
|
||||
#define RCS_ASS "$Id$"
|
||||
|
||||
/*
|
||||
* compile time options
|
||||
*/
|
||||
|
||||
#define DUMP 1 /* dump between passes */
|
||||
/* #define TIMING 1 /* some timing measurements */
|
||||
#define JOHAN 1 /* dump the loaded instructions */
|
||||
#define MEMUSE 1 /* print memory usage statistics */
|
||||
|
||||
#ifndef DUMP
|
||||
#define dump(x) /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef TIMING
|
||||
#define timing() /* nothing */
|
||||
#endif
|
||||
|
||||
#ifndef MEMUSE
|
||||
#define memuse() /* nothing */
|
||||
#endif
|
||||
|
||||
/* Used to clear the upper byte(s) of characters.
|
||||
Not nessecary if your C-compiler does not sign-extend char's
|
||||
*/
|
||||
|
||||
#ifdef CPM
|
||||
# define LC(ch) ( ((ch)<'A' | (ch)>'Z' ) ? (ch) : ((ch)-('A'-'a')))
|
||||
#else
|
||||
# define LC(ch) (ch)
|
||||
#endif
|
||||
|
||||
#define ctrunc(val) ( (val)&0377 )
|
||||
|
||||
#define odd(n) ((n)&1) /* Boolean odd function */
|
||||
|
||||
#define lnp_cast (line_t *)
|
||||
#define gbp_cast (glob_t *)
|
||||
#define lbp_cast (locl_t *)
|
||||
#define prp_cast (proc_t *)
|
||||
#define ptp_cast (ptab_t *)
|
||||
#define rlp_cast (relc_t *)
|
||||
#define pst_cast (stat_t *)
|
||||
#define chp_cast (char *)
|
||||
#define ipp_cast (int **)
|
||||
#define iip_cast (int *)
|
||||
#define int_cast (int )
|
||||
|
||||
typedef struct lines line_t;
|
||||
typedef struct loc_label locl_t;
|
||||
typedef struct glob_label glob_t;
|
||||
typedef struct rel relc_t;
|
||||
typedef struct procstat stat_t;
|
||||
typedef struct sizes siz_t;
|
||||
typedef struct ar_hdr arch_t;
|
||||
typedef struct procs proc_t;
|
||||
typedef struct proctab ptab_t;
|
||||
typedef char * area_t;
|
||||
typedef long cons_t;
|
||||
|
||||
typedef union {
|
||||
cons_t ad_i;
|
||||
locl_t *ad_lp;
|
||||
glob_t *ad_gp;
|
||||
proc_t *ad_pp;
|
||||
struct sad_ln {
|
||||
short ln_extra;
|
||||
short ln_first;
|
||||
} ad_ln ;
|
||||
struct sad_df {
|
||||
cons_t df_i;
|
||||
glob_t *df_gp;
|
||||
} ad_df;
|
||||
} addr_u;
|
||||
|
||||
typedef union {
|
||||
cons_t rel_i;
|
||||
locl_t *rel_lp;
|
||||
glob_t *rel_gp;
|
||||
} rel_u;
|
||||
|
||||
#define FOFFSET long /* offset into file */
|
||||
|
||||
/*
|
||||
* Global variables and definitions for EM1-assembler/loader
|
||||
*/
|
||||
|
||||
#define DEFINING 0 /* parameters for glolookup */
|
||||
#define OCCURRING 1
|
||||
#define INTERNING 2
|
||||
#define EXTERNING 3
|
||||
#define SEARCHING 4
|
||||
#define ENTERING 5
|
||||
|
||||
#define PRO_OCC 0 /* parameters for prolookup */
|
||||
#define PRO_DEF 1
|
||||
#define PRO_INT 2
|
||||
#define PRO_EXT 3
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define MAXBYTE 255
|
||||
|
||||
#define MAXSTRING 200 /* Maximum string length accepted */
|
||||
#define LOCLABSIZE 128 /* size of local label hash table */
|
||||
/* may not be smaller */
|
||||
#define ABSSIZE 8
|
||||
|
||||
struct lines {
|
||||
char instr_num; /* index into mnemon[] */
|
||||
char type1; /* see below */
|
||||
line_t *l_next; /* next in chain */
|
||||
char *opoff; /* pointer into opchoice[] */
|
||||
addr_u ad; /* depending on type, various pointers */
|
||||
};
|
||||
|
||||
/* contents of type1 */
|
||||
#define MISSING 0 /* no operand */
|
||||
#define CONST 1 /* ad contains operand */
|
||||
#define PROCNAME 2 /* ad contains struct procs pointer */
|
||||
#define GLOSYM 3 /* ad contains pointer into mproc[] */
|
||||
#define LOCSYM 4 /* ad contains pointer into locs[] */
|
||||
#define GLOOFF 5 /* ad contains CONST and GLOSYM in ad_df */
|
||||
#define LINES 6 /* Line number setting, only param of pseudo*/
|
||||
#define VALLOW 7 /* value's between LOW and HIGH are x-MID */
|
||||
#define VALMID 50
|
||||
#define VALHIGH 127 /* to avoid sign extension problems */
|
||||
|
||||
#define VAL1(x) ((x)-VALMID)
|
||||
|
||||
/* Used to indicate a invalid contents of opoff */
|
||||
#define NO_OFF ((char *)-1)
|
||||
|
||||
struct loc_label {
|
||||
locl_t *l_chain; /* The next label with same low order bits */
|
||||
char l_hinum; /* high bits of number of label */
|
||||
char l_defined; /* see below */
|
||||
int l_min,l_max; /* boundaries of value */
|
||||
};
|
||||
|
||||
/* The structure containing procedure pertinent data */
|
||||
/* Used for environment stacking for nested PRO's */
|
||||
|
||||
struct procstat {
|
||||
line_t *s_fline; /* points to first line of procedure */
|
||||
locl_t (*s_locl)[1]; /* pointer to local labels */
|
||||
proc_t *s_curpro; /* identifies current procedure */
|
||||
relc_t *s_fdata; /* last datareloc before procedure */
|
||||
stat_t *s_prevstat; /* backward chain of nested procedures */
|
||||
} ;
|
||||
|
||||
/* contents of l_defined */
|
||||
#define EMPTY 0 /* Empty slot */
|
||||
#define NO 1 /* not defined yet */
|
||||
#define YES 2 /* defined */
|
||||
#define SEEN 3 /* intermediate state */
|
||||
#define NOTPRESENT 4 /* Undefined and error message given */
|
||||
|
||||
struct glob_label {
|
||||
char *g_name;
|
||||
char g_status; /* see below */
|
||||
union {
|
||||
cons_t g_addr; /* value if status&DEF */
|
||||
struct glob_label *g_gp; /* ref. to xglobs */
|
||||
} g_val ;
|
||||
};
|
||||
|
||||
#define glostring(gl) ((gl)->g_name)
|
||||
|
||||
/* contents of g_status */
|
||||
#define DEF 01 /* defined */
|
||||
#define OCC 02 /* used */
|
||||
#define EXT 04 /* external */
|
||||
|
||||
struct rel { /* for relocation tables */
|
||||
relc_t *r_next; /* chain */
|
||||
FOFFSET r_off; /* offset in text/data of word to relocate */
|
||||
rel_u r_val; /* constant or pointer to global symbol */
|
||||
int r_typ; /* different use in text or data */
|
||||
};
|
||||
|
||||
/*
|
||||
* When used with textrelocation r_typ contains the flag bits as defined
|
||||
* in ip_spec.h together with the RELMNS bit if r_val contains an integer
|
||||
*/
|
||||
|
||||
#define RELMNS 020000 /* indicates integer i.s.o. glob */
|
||||
|
||||
/* Contents of r_typ when used with data relocation */
|
||||
#define RELNULL 0
|
||||
#define RELGLO 1
|
||||
#define RELHEAD 2
|
||||
#define RELLOC 3
|
||||
#define RELADR 4
|
||||
|
||||
/* modes of data output */
|
||||
#define DATA_NUL 0
|
||||
#define DATA_REP 1
|
||||
#define DATA_CONST 2
|
||||
#define DATA_BSS 3
|
||||
#define DATA_DPTR 4
|
||||
#define DATA_IPTR 5
|
||||
#define DATA_ICON 6
|
||||
#define DATA_UCON 7
|
||||
#define DATA_FCON 8
|
||||
#define DATA_BYTES 9
|
||||
|
||||
/* name of procedure to be called first */
|
||||
#define MAIN "_m_a_i_n"
|
||||
|
||||
/* headers of datablocks written */
|
||||
#define HEADREP 0
|
||||
#define HEADBSS 1
|
||||
#define HEADBYTE 2
|
||||
#define HEADCONST 3
|
||||
#define HEADDPTR 4
|
||||
#define HEADIPTR 5
|
||||
#define HEADICON 6
|
||||
#define HEADUCON 7
|
||||
#define HEADFCON 8
|
||||
|
||||
#define NDEFAULT 4 /* number of different sizes available */
|
||||
struct sizes {
|
||||
int n_mlab; /* # of global labels per module */
|
||||
int n_glab; /* # of extern global labels */
|
||||
int n_mproc; /* # of local procs per module */
|
||||
int n_xproc; /* # of external procs */
|
||||
int n_proc; /* total # of procedures */
|
||||
};
|
||||
|
||||
struct procs { /* format of mprocs[] and xprocs[] */
|
||||
char *p_name;
|
||||
char p_status; /* same bits as g_status except REL */
|
||||
int p_num; /* unique procedure descriptor */
|
||||
};
|
||||
|
||||
struct proctab {
|
||||
cons_t pr_off; /* distance from pb */
|
||||
cons_t pr_loc; /* number of bytes locals */
|
||||
};
|
||||
368
util/ass/ass30.c
368
util/ass/ass30.c
@@ -1,368 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ass00.h"
|
||||
#include "assex.h"
|
||||
#include "ip_spec.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
static char rcs_ip[] = RCS_IP ;
|
||||
#endif
|
||||
|
||||
short opt_line ; /* max_line_no - # lines removed from end
|
||||
after perfoming exc's.
|
||||
Used to estimate the distance in # of
|
||||
instructions.
|
||||
*/
|
||||
/*
|
||||
** Determine the exact instruction length & format where possible, and the
|
||||
** the upper and lower limits otherwise. Enter limits in labeltable
|
||||
*/
|
||||
pass_3()
|
||||
{
|
||||
register line_t *lnp, *rev_lnp;
|
||||
line_t *tmp_lnp;
|
||||
locl_t *lbp;
|
||||
int min_l, max_l, min_bytes;
|
||||
short last_line ;
|
||||
short hol_err_line ;
|
||||
register insno ;
|
||||
|
||||
pass = 3;
|
||||
opt_line= line_num ; hol_err_line=0 ;
|
||||
min_bytes = max_bytes = 0; rev_lnp= lnp_cast 0 ;
|
||||
for (lnp = pstate.s_fline ; lnp ; opt_line--, line_num-- ) {
|
||||
pstate.s_fline= lnp;
|
||||
insno = ctrunc(lnp->instr_num);
|
||||
switch( insno ) {
|
||||
case sp_fpseu :
|
||||
last_line = line_num ;
|
||||
line_num = lnp->ad.ad_ln.ln_first ;
|
||||
opt_line -= lnp->ad.ad_ln.ln_extra ;
|
||||
lnp->ad.ad_ln.ln_first= last_line ;
|
||||
break ;
|
||||
case sp_ilb1 :
|
||||
lbp = lnp->ad.ad_lp;
|
||||
lbp->l_defined = SEEN;
|
||||
lbp->l_min = min_bytes;
|
||||
lbp->l_max = max_bytes;
|
||||
break ;
|
||||
default:
|
||||
if ( lnp->type1==CONST && (em_flag[insno]&EM_PAR)==PAR_G ) {
|
||||
if (holbase != 0) {
|
||||
if (lnp->ad.ad_i >= holsize) {
|
||||
hol_err_line= line_num ;
|
||||
}
|
||||
lnp->ad.ad_i += holbase;
|
||||
}
|
||||
} else
|
||||
if ( lnp->type1>=VALLOW && (em_flag[insno]&EM_PAR)==PAR_G ) {
|
||||
if (holbase != 0) {
|
||||
pstate.s_fline= lnp->l_next ;
|
||||
newline(CONST) ;
|
||||
pstate.s_fline->instr_num= insno ;
|
||||
pstate.s_fline->ad.ad_i=
|
||||
VAL1(lnp->type1)+holbase ;
|
||||
freearea((area_t)lnp,
|
||||
(unsigned)linesize[VALLOW]) ;
|
||||
lnp= pstate.s_fline ;
|
||||
if ( VAL1(lnp->type1) >= holsize) {
|
||||
hol_err_line= line_num ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !valid(lnp) ) fatal("Invalid operand") ;
|
||||
|
||||
determine_props(lnp, &min_l, &max_l);
|
||||
min_bytes += min_l; max_bytes += max_l;
|
||||
break ;
|
||||
}
|
||||
tmp_lnp= lnp->l_next ;
|
||||
lnp->l_next= rev_lnp ; rev_lnp= lnp ;
|
||||
lnp= tmp_lnp ;
|
||||
}
|
||||
pstate.s_fline= rev_lnp ;
|
||||
if ( hol_err_line ) {
|
||||
line_num= hol_err_line ;
|
||||
werror("address exceeds holsize") ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Determine the format that should be used for each instruction,
|
||||
** depending on its offsets
|
||||
*/
|
||||
|
||||
determine_props(lnp, min_len, max_len)
|
||||
line_t *lnp;
|
||||
int *min_len, *max_len;
|
||||
{
|
||||
cons_t val ;
|
||||
register int insno ;
|
||||
register char *f_off, *l_off ;
|
||||
char defined ;
|
||||
|
||||
insno=ctrunc(lnp->instr_num) ;
|
||||
val=parval(lnp,&defined) ;
|
||||
if ( !defined ) {
|
||||
switch(em_flag[insno]&EM_PAR) {
|
||||
case PAR_NO:
|
||||
case PAR_W:
|
||||
f_off = findnop(insno) ;
|
||||
break ;
|
||||
case PAR_G:
|
||||
/* We want the maximum address that is a multiple
|
||||
of the wordsize.
|
||||
Assumption: there is no shortie for
|
||||
intr max_word_multiple
|
||||
where intr is a instruction allowing parameters
|
||||
that are not a word multiple (PAR_G).
|
||||
*/
|
||||
f_off = findfit(insno, maxadr&(~(wordsize-1))) ;
|
||||
break ;
|
||||
case PAR_B:
|
||||
f_off = findfit(insno, (cons_t)0) ;
|
||||
l_off = findfit(insno, val ) ;
|
||||
if ( f_off != l_off ) {
|
||||
*min_len=oplength(*f_off) ;
|
||||
*max_len=oplength(*l_off) ;
|
||||
lnp->opoff = NO_OFF ;
|
||||
return ;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
} else {
|
||||
f_off = findfit(insno,val) ;
|
||||
}
|
||||
lnp->opoff = f_off ;
|
||||
*min_len = *max_len = oplength(*f_off) ;
|
||||
}
|
||||
|
||||
char *findfit(instr,val) int instr ; cons_t val ; {
|
||||
register char *currc,*endc ;
|
||||
int found, flags, number ;
|
||||
char *opc ;
|
||||
|
||||
endc = opindex[instr+1] ;
|
||||
for ( currc=opindex[instr], found=0 ;
|
||||
!found && currc<endc ; currc++ ) {
|
||||
opc = currc ;
|
||||
flags=ctrunc(*currc++) ;
|
||||
switch ( flags&OPTYPE ) {
|
||||
case OPNO :
|
||||
continue ;
|
||||
case OPMINI :
|
||||
case OPSHORT :
|
||||
number=ctrunc(*++currc) ;
|
||||
}
|
||||
found = opfit(flags, number, val, em_flag[instr]&EM_PAR ) ;
|
||||
}
|
||||
if ( !found ) fatal("Cannot find interpreter opcode") ;
|
||||
return opc ;
|
||||
}
|
||||
|
||||
char *findnop(instr) int instr ; {
|
||||
register char *currc,*endc ;
|
||||
|
||||
endc = opindex[instr+1] ;
|
||||
for ( currc=opindex[instr] ; currc<endc ; currc++ ) {
|
||||
switch ( ctrunc(*currc)&OPTYPE ) {
|
||||
case OPNO :
|
||||
return currc ;
|
||||
case OPSHORT :
|
||||
case OPMINI :
|
||||
currc++ ;
|
||||
}
|
||||
currc++ ;
|
||||
}
|
||||
fatal("Cannot find interpreter opcode") ;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
int opfit(flag,number,val,i_flag)
|
||||
int i_flag,flag,number ; cons_t val ; {
|
||||
/* Number is invalid if flag does not contain MINI or SHORT */
|
||||
switch ( flag&OPRANGE ) {
|
||||
case OP_POS :
|
||||
if ( val<0 ) return 0 ;
|
||||
break ;
|
||||
case OP_NEG :
|
||||
if ( val>=0 ) return 0 ;
|
||||
break ;
|
||||
}
|
||||
if ( flag&OPWORD ) {
|
||||
if ( val%wordsize ) return 0 ;
|
||||
val /= wordsize ;
|
||||
}
|
||||
if ( flag&OPNZ ) {
|
||||
if ( val==0 ) return 0 ;
|
||||
val-- ;
|
||||
}
|
||||
switch ( flag&OPTYPE ) {
|
||||
case OPMINI :
|
||||
if ( val<0 ) val = -1-val ;
|
||||
return val>=0 && val<number ;
|
||||
case OPSHORT :
|
||||
if ( val<0 ) val = -1-val ;
|
||||
return val>=0 && val<number*256 ;
|
||||
case OP16U:
|
||||
return val>=0 && val<=65535L &&
|
||||
( i_flag!=PAR_G || val<=maxadr ) ;
|
||||
case OP16 :
|
||||
return val>= -32768 && val<=32767 ;
|
||||
case OP32 :
|
||||
return TRUE ;
|
||||
default :
|
||||
fatal("illegal OPTYPE value") ;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
int oplength(flag) int flag ; {
|
||||
int cnt ;
|
||||
|
||||
cnt=1 ;
|
||||
if ( flag&OPESC ) cnt++ ;
|
||||
switch( flag&OPTYPE ) {
|
||||
case OPNO :
|
||||
case OPMINI : break ;
|
||||
case OP8 :
|
||||
case OPSHORT : cnt++ ; break ;
|
||||
case OP16U:
|
||||
case OP16 : cnt+=2 ; break ;
|
||||
case OP32 : cnt+=5 ; break ;
|
||||
case OP64 : cnt+=9 ; break ;
|
||||
}
|
||||
return cnt ;
|
||||
}
|
||||
|
||||
/*
|
||||
** return estimation of value of parameter
|
||||
*/
|
||||
cons_t parval(lnp,defined)
|
||||
line_t *lnp;
|
||||
char *defined;
|
||||
{
|
||||
register int type;
|
||||
register locl_t *lbp;
|
||||
register glob_t *gbp;
|
||||
cons_t offs ;
|
||||
|
||||
*defined = TRUE ;
|
||||
type = lnp->type1;
|
||||
switch(type) {
|
||||
default: if ( type>=VALLOW && type<=VALHIGH )
|
||||
return VAL1(type) ;
|
||||
error("bad type during parval");
|
||||
break;
|
||||
case CONST:
|
||||
return(lnp->ad.ad_i);
|
||||
case GLOSYM:
|
||||
case GLOOFF:
|
||||
if ( type!=GLOOFF) {
|
||||
gbp = lnp->ad.ad_gp;
|
||||
offs= 0 ;
|
||||
} else {
|
||||
gbp =lnp->ad.ad_df.df_gp ;
|
||||
offs=lnp->ad.ad_df.df_i ;
|
||||
}
|
||||
if(gbp->g_status&DEF)
|
||||
return(gbp->g_val.g_addr+offs);
|
||||
else {
|
||||
*defined = FALSE ;
|
||||
return offs ;
|
||||
}
|
||||
case LOCSYM:
|
||||
lbp = lnp->ad.ad_lp;
|
||||
switch(pass) {
|
||||
default:error("bad pass in parval");
|
||||
case 3:
|
||||
*defined = FALSE;
|
||||
switch(lbp->l_defined) {
|
||||
default : fatal("Illegal local label") ;
|
||||
case NO :
|
||||
error("Undefined local label") ;
|
||||
lbp->l_defined= NOTPRESENT ;
|
||||
case NOTPRESENT:
|
||||
return max_bytes;
|
||||
case SEEN :
|
||||
return max_bytes - lbp->l_min ;
|
||||
case YES :
|
||||
/* l_min contains line_num
|
||||
adjusted for exc's.
|
||||
*/
|
||||
return (lbp->l_min - opt_line -1 ) * maxinsl ;
|
||||
}
|
||||
case 4: if(lbp->l_defined == YES)
|
||||
return(lbp->l_min-prog_size-maxinsl);
|
||||
return max_bytes - lbp->l_max- prog_size;
|
||||
case 5: if (lbp->l_defined == YES )
|
||||
return lbp->l_min ;
|
||||
*defined = FALSE ;
|
||||
break ;
|
||||
}
|
||||
break;
|
||||
case MISSING:
|
||||
*defined = FALSE ;
|
||||
break;
|
||||
case PROCNAME:
|
||||
return(lnp->ad.ad_pp->p_num);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
int valid(lnp) register line_t *lnp ; {
|
||||
cons_t val ;
|
||||
int type ;
|
||||
|
||||
type = lnp->type1 ;
|
||||
if ( type>=VALLOW && type<=VALHIGH ) {
|
||||
val= VAL1(type) ;
|
||||
type= CONST ;
|
||||
} else if ( type==CONST ) val = lnp->ad.ad_i ;
|
||||
switch ( em_flag[ctrunc(lnp->instr_num)]&EM_PAR ) {
|
||||
case PAR_NO:
|
||||
return type==MISSING ;
|
||||
case PAR_C:
|
||||
if ( type!=CONST ) return FALSE;
|
||||
if ( val>maxint && val<=maxunsig ) {
|
||||
lnp->ad.ad_i = val -maxunsig -1 ;
|
||||
}
|
||||
return TRUE ;
|
||||
case PAR_D:
|
||||
if ( type!=CONST ) return FALSE;
|
||||
if ( val>maxdint && val<=maxdunsig ) {
|
||||
lnp->ad.ad_i = val -maxdunsig -1 ;
|
||||
}
|
||||
return TRUE ;
|
||||
case PAR_L:
|
||||
case PAR_F:
|
||||
return type==CONST ;
|
||||
case PAR_N:
|
||||
return type==CONST && val>=0 ;
|
||||
case PAR_G:
|
||||
return type==CONST || type==GLOSYM || type==GLOOFF ;
|
||||
case PAR_W:
|
||||
if ( type==MISSING ) return TRUE ;
|
||||
case PAR_S:
|
||||
return type==CONST && val>0 && val%wordsize==0 ;
|
||||
case PAR_Z:
|
||||
return type==CONST && val>=0 && val%wordsize==0 ;
|
||||
case PAR_O:
|
||||
return type==CONST && val>=0 &&
|
||||
( val >= wordsize ? val%wordsize : wordsize%val ) == 0 ;
|
||||
case PAR_P:
|
||||
return type==PROCNAME ;
|
||||
case PAR_B:
|
||||
return type==LOCSYM ;
|
||||
case PAR_R:
|
||||
return type==CONST && val>=0 && val<=3 ;
|
||||
default:
|
||||
fatal("Unknown parameter type") ;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ass00.h"
|
||||
#include "assex.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Make scans to do final assignment of instruction sizes & formats
|
||||
** to those not already done. assign final values to labels
|
||||
*/
|
||||
pass_4()
|
||||
{
|
||||
register line_t *lnp;
|
||||
register locl_t *lbp;
|
||||
int min_l, max_l;
|
||||
int instr;
|
||||
|
||||
pass = 4;
|
||||
prog_size= 0 ;
|
||||
for (lnp = pstate.s_fline ; lnp ; lnp= lnp->l_next, line_num++) {
|
||||
instr = ctrunc(lnp->instr_num);
|
||||
if ( instr==sp_fpseu ) {
|
||||
line_num = lnp->ad.ad_ln.ln_first ;
|
||||
continue ;
|
||||
}
|
||||
if ( instr==sp_ilb1 ) {
|
||||
lbp = lnp->ad.ad_lp;
|
||||
lbp->l_min= prog_size; lbp->l_defined = YES;
|
||||
continue ;
|
||||
}
|
||||
|
||||
if (lnp->opoff == NO_OFF)
|
||||
{
|
||||
determine_props(lnp, &min_l, &max_l);
|
||||
if (min_l != max_l)
|
||||
fatal("no size known");
|
||||
} else {
|
||||
min_l = oplength(*(lnp->opoff)) ;
|
||||
}
|
||||
prog_size += min_l ;
|
||||
}
|
||||
}
|
||||
184
util/ass/ass50.c
184
util/ass/ass50.c
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ass00.h"
|
||||
#include "assex.h"
|
||||
#include "ip_spec.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Pass 5 of EM1 assembler/loader
|
||||
** Fix reloc tables
|
||||
** Write out code
|
||||
*/
|
||||
|
||||
pass_5() {
|
||||
register line_t *lnp;
|
||||
cons_t off1;
|
||||
char defined ;
|
||||
int afterlength, partype ;
|
||||
register int inslength, ope;
|
||||
char *op_curr ;
|
||||
|
||||
pass = 5;
|
||||
afterlength = 0;
|
||||
for (lnp = pstate.s_fline ; lnp ; lnp= lnp->l_next, line_num++ ) {
|
||||
ope = ctrunc(lnp->instr_num);
|
||||
if ( ope==sp_ilb1 ) continue ;
|
||||
if ( ope==sp_fpseu ) {
|
||||
line_num = lnp->ad.ad_ln.ln_first ;
|
||||
continue ;
|
||||
}
|
||||
off1 = parval(lnp,&defined);
|
||||
if ( (op_curr = lnp->opoff)==NO_OFF ) {
|
||||
fatal("opoff assertion failed") ;
|
||||
}
|
||||
inslength = oplength(*op_curr) ;
|
||||
afterlength += inslength ;
|
||||
|
||||
/*
|
||||
* Change absolute offset to a relative for branches.
|
||||
*/
|
||||
|
||||
|
||||
partype= em_flag[ope]&EM_PAR ;
|
||||
if ( partype==PAR_B && defined ) {
|
||||
off1 -= afterlength;
|
||||
}
|
||||
|
||||
#ifdef JOHAN
|
||||
if ( jflag ) {
|
||||
extern char em_mnem[][4] ;
|
||||
printf("%s %ld\n",em_mnem[ope],off1) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( !defined && partype==PAR_G ) { /* must be external */
|
||||
text_reloc((lnp->type1==GLOSYM ?
|
||||
lnp->ad.ad_gp:lnp->ad.ad_df.df_gp),
|
||||
(FOFFSET)(textbytes+afterlength-inslength) ,
|
||||
op_curr-opchoice);
|
||||
xputarb(inslength,off1,tfile);
|
||||
textoff += inslength ;
|
||||
} else {
|
||||
genop(op_curr,off1,partype) ;
|
||||
}
|
||||
} /* end forloop */
|
||||
line_num-- ;
|
||||
|
||||
patchcase();
|
||||
textbytes += prog_size;
|
||||
if ( textbytes>maxadr ) fatal("Maximum code area size exceeded") ;
|
||||
|
||||
} /* end pass_5 */
|
||||
|
||||
genop(startc,value,i_flag) char *startc ; cons_t value ; int i_flag ; {
|
||||
char *currc ;
|
||||
register flag ;
|
||||
char opc ;
|
||||
|
||||
/*
|
||||
* Real code generation.
|
||||
*/
|
||||
|
||||
currc= startc ;
|
||||
flag = ctrunc(*currc++);
|
||||
opc = *currc++;
|
||||
if ( (flag&OPTYPE)!=OPNO ) {
|
||||
|
||||
if ( !opfit(flag,*currc,value,i_flag) ) {
|
||||
fatal("parameter value unsuitable for selected opcode") ;
|
||||
}
|
||||
if ( flag&OPWORD ) {
|
||||
if ( value%wordsize!=0 ) {
|
||||
error("parameter not word multiple");
|
||||
}
|
||||
value /= wordsize ;
|
||||
}
|
||||
if ( flag&OPNZ ) {
|
||||
if ( value<=0 ) error("negative parameter");
|
||||
value-- ;
|
||||
}
|
||||
}
|
||||
if ( flag&OPESC ) put8(ESC) ;
|
||||
|
||||
switch ( flag&OPTYPE ) {
|
||||
case OPMINI :
|
||||
opc += value<0 ? -1-value : value ;
|
||||
break ;
|
||||
case OPSHORT :
|
||||
if ( value<0 ) {
|
||||
opc += -1-(value>>8) ;
|
||||
} else {
|
||||
opc += value>>8 ;
|
||||
}
|
||||
break ;
|
||||
case OP32 :
|
||||
case OP64 :
|
||||
put8(ESC_L) ;
|
||||
}
|
||||
|
||||
#ifdef DUMP
|
||||
if ( c_flag ) {
|
||||
switch(flag&OPTYPE) {
|
||||
case OP32 :
|
||||
case OP64 :
|
||||
opcnt3[opc&0377]= 1 ;
|
||||
break ;
|
||||
default :
|
||||
if ( flag&OPESC ) opcnt2[opc&0377]= 1 ;
|
||||
else opcnt1[opc&0377]= 1 ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
put8(opc) ;
|
||||
switch( flag&OPTYPE ) {
|
||||
case OPNO:
|
||||
case OPMINI:
|
||||
break ;
|
||||
case OPSHORT:
|
||||
case OP8:
|
||||
put8((char)value) ;
|
||||
break ;
|
||||
case OP16:
|
||||
case OP16U:
|
||||
put16(int_cast value) ;
|
||||
break ;
|
||||
case OP32:
|
||||
put32(value) ;
|
||||
break ;
|
||||
case OP64:
|
||||
put64(value) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
patchcase() {
|
||||
register relc_t *r;
|
||||
register locl_t *k;
|
||||
|
||||
if ( r= pstate.s_fdata ) {
|
||||
r= r->r_next ;
|
||||
} else {
|
||||
r= f_data ;
|
||||
}
|
||||
for( ; r ; r= r->r_next ) {
|
||||
if (r->r_typ == RELLOC) {
|
||||
r->r_typ = RELADR;
|
||||
k = r->r_val.rel_lp;
|
||||
if (k->l_defined==YES)
|
||||
r->r_val.rel_i = k->l_min + textbytes;
|
||||
else
|
||||
error("case label at line %d undefined",
|
||||
k->l_min);
|
||||
}
|
||||
}
|
||||
}
|
||||
204
util/ass/ass60.c
204
util/ass/ass60.c
@@ -1,204 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ass00.h"
|
||||
#include "assex.h"
|
||||
#include "ip_spec.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
#ifdef DUMP
|
||||
static char *typestr[] =
|
||||
{"missing","const","procname","glosym","locsym","glosym+off","pseudo"};
|
||||
static char *labstr[] = {"EMPTY","no","yes","seen","notpresent"};
|
||||
static char formstr[] = { 'm','s','-','1','2','4','8' };
|
||||
static char *r_data[] = { "null","glob","head","loc","adr" };
|
||||
|
||||
cons_t nicepr(typ,ap) addr_u *ap; {
|
||||
register proc_t *pl;
|
||||
|
||||
switch (typ) {
|
||||
case CONST:
|
||||
return(ap->ad_i);
|
||||
case LOCSYM:
|
||||
return(int_cast ap->ad_lp);
|
||||
case GLOOFF:
|
||||
return(ap->ad_df.df_gp - mglobs);
|
||||
case GLOSYM:
|
||||
return(ap->ad_gp - mglobs);
|
||||
case PROCNAME:
|
||||
pl = ap->ad_pp;;
|
||||
if (pl->p_status&EXT)
|
||||
return((pl-xprocs)+1000);
|
||||
else
|
||||
return(pl-mprocs);
|
||||
default:
|
||||
if ( typ>=VALLOW && typ<=VALHIGH ) return VAL1(typ) ;
|
||||
break ;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
char *pflags(flg) int flg ; {
|
||||
static char res[9] ;
|
||||
register char *cp ;
|
||||
|
||||
cp=res ;
|
||||
if ( flg&OPESC ) *cp++ = 'e' ;
|
||||
switch ( flg&OPRANGE ) {
|
||||
case OP_NEG : *cp++ = 'N' ; break ;
|
||||
case OP_POS : *cp++ = 'P' ; break ;
|
||||
}
|
||||
if ( flg&OPWORD ) *cp++ = 'w' ;
|
||||
if ( flg&OPNZ ) *cp++ = 'o' ;
|
||||
*cp++ = formstr[flg&OPTYPE] ;
|
||||
*cp++ = 0 ;
|
||||
return res ;
|
||||
}
|
||||
|
||||
|
||||
dump(n)
|
||||
{
|
||||
register glob_t *gb;
|
||||
register line_t *ln;
|
||||
register locl_t *lbp;
|
||||
register locl_t *lbhead;
|
||||
proc_t *pl;
|
||||
int i;
|
||||
int insno;
|
||||
extern char em_mnem[][4] ;
|
||||
|
||||
if (d_flag==0) return;
|
||||
if ( (n==0 && d_flag) || (n==4 && d_flag>=2) || (n<100 && d_flag>=3) ) {
|
||||
printf("\nEM1-assembler ***** pass %1d complete:\n",n);
|
||||
printf("current size %ld\n",prog_size) ;
|
||||
printf(" %9.9s%9.9s%14.14s%8.8s%8.8s\n", "instr_nr",
|
||||
"type1","addr1","length","format");
|
||||
for (ln = pstate.s_fline ; ln ;
|
||||
ln = ln->l_next, n>=3 || n==0 ? i++ : i-- ) {
|
||||
insno = ctrunc(ln->instr_num) ;
|
||||
if ( insno==sp_fpseu ) {
|
||||
i= ln->ad.ad_ln.ln_first ;
|
||||
continue ;
|
||||
}
|
||||
printf("%4d ",i) ;
|
||||
switch(insno) {
|
||||
default:
|
||||
printf(
|
||||
" %3.3s",em_mnem[insno]) ;
|
||||
break ;
|
||||
case sp_ilb1:
|
||||
printf("l ");
|
||||
break;
|
||||
case sp_fpseu:
|
||||
printf("p ");
|
||||
break;
|
||||
}
|
||||
printf(" %9.9s%14ld",
|
||||
typestr[ln->type1<VALLOW ? ln->type1 : CONST],
|
||||
nicepr(ln->type1,&ln->ad)) ;
|
||||
if ( ln->opoff != NO_OFF )
|
||||
printf("%5d %.6s",
|
||||
oplength(*(ln->opoff)),pflags(*(ln->opoff)));
|
||||
printf("\n");
|
||||
}
|
||||
printf("\n %8s%8s%8s%8s%8s\n","labnum","labid","minval","maxval",
|
||||
"defined");
|
||||
for ( i = 0, lbhead= *pstate.s_locl ; i<LOCLABSIZE ; lbhead++,i++) {
|
||||
if ( lbhead->l_defined!=EMPTY ) printf("%4d\n",i);
|
||||
for (lbp= lbhead; lbp != lbp_cast 0; lbp= lbp->l_chain) {
|
||||
if (lbp->l_defined!=EMPTY)
|
||||
printf(" %8d%8d%8d%8d %-s\n",
|
||||
lbp->l_hinum*LOCLABSIZE + i,
|
||||
int_cast lbp,lbp->l_min,
|
||||
lbp->l_max, labstr[lbp->l_defined]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ( (n==0 || n>=100) && d_flag) || (n<=1 && d_flag>=2) ) {
|
||||
if ( n==0 || n==100 ) {
|
||||
printf("File %s",curfile) ;
|
||||
if ( archmode ) printf("(%.14s)",archhdr.ar_name);
|
||||
printf(" :\n\n") ;
|
||||
}
|
||||
printf("Local data labels:\n");
|
||||
printf(
|
||||
"\n\t%8.8s %8.8s %8.8s\n","g_name","g_status","g_addr");
|
||||
for (gb = mglobs,i = 0;gb < &mglobs[oursize->n_mlab]; gb++, i++)
|
||||
if (gb->g_name[0] != 0) {
|
||||
printf("%5d\t%8.6s",i,gb->g_name);
|
||||
printf(" %8o %8ld\n",gb->g_status,gb->g_val.g_addr);
|
||||
}
|
||||
printf("\n\nGlobal data labels\n");
|
||||
printf("\n\t%8.8s %8.8s %8.8s\n",
|
||||
"g_name","g_status","g_addr");
|
||||
for (gb = xglobs,i = 0;gb < &xglobs[oursize->n_glab]; gb++, i++)
|
||||
if (gb->g_name != 0) {
|
||||
printf("%5d\t%8.6s",i,gb->g_name);
|
||||
printf(" %8o %8ld\n",gb->g_status,gb->g_val.g_addr);
|
||||
}
|
||||
printf("\n\nLocal procedures\n");
|
||||
printf("\n\t%8.8s%8s%8s\t%8s%8s\n",
|
||||
"name","status","num","off","locals");
|
||||
for (pl=mprocs;pl< &mprocs[oursize->n_mproc]; pl++)
|
||||
if (pl->p_name) {
|
||||
printf("%4d\t%-8s%8o%8d",
|
||||
pl-mprocs,pl->p_name,pl->p_status,pl->p_num);
|
||||
if (pl->p_status&DEF)
|
||||
printf("\t%8ld%8ld",proctab[pl->p_num].pr_off,
|
||||
proctab[pl->p_num].pr_loc);
|
||||
printf("\n");
|
||||
}
|
||||
printf("\nGlobal procedures\n");
|
||||
printf("\n\t%8s%8s%8s\t%8s%8s\n",
|
||||
"name","status","num","off","locals");
|
||||
for (pl=xprocs;pl< &xprocs[oursize->n_xproc]; pl++)
|
||||
if (pl->p_name) {
|
||||
printf("%4d\t%-8s%8o%8d",
|
||||
pl-xprocs,pl->p_name,pl->p_status,pl->p_num);
|
||||
if (pl->p_status&DEF)
|
||||
printf("\t%8ld%8ld",proctab[pl->p_num].pr_off,
|
||||
proctab[pl->p_num].pr_loc);
|
||||
printf("\n");
|
||||
}
|
||||
if ( r_flag ) {
|
||||
register relc_t *rl ;
|
||||
printf("\nData relocation\n") ;
|
||||
printf("\n\t%10s %10s %10s\n","offset","type","value");
|
||||
for ( rl=f_data ; rl ; rl= rl->r_next ) {
|
||||
printf("\t%10ld %10s ",rl->r_off,r_data[rl->r_typ]);
|
||||
switch(rl->r_typ) {
|
||||
case RELADR:
|
||||
case RELHEAD:
|
||||
printf("%10ld\n",rl->r_val.rel_i) ;
|
||||
break ;
|
||||
case RELGLO:
|
||||
printf("%8.8s\n",rl->r_val.rel_gp->g_name) ;
|
||||
break ;
|
||||
case RELLOC:
|
||||
printf("%10d\n",rl->r_val.rel_lp) ;
|
||||
break ;
|
||||
case RELNULL:
|
||||
printf("\n"); break ;
|
||||
}
|
||||
}
|
||||
printf("\n\nText relocation\n") ;
|
||||
printf("\n\t%10s %10s %10s\n","offset","flags","value");
|
||||
for ( rl=f_text; rl ; rl= rl->r_next ) {
|
||||
printf("\t%10ld %10s ",
|
||||
rl->r_off,pflags(opchoice[rl->r_typ&~RELMNS])) ;
|
||||
if ( rl->r_typ&RELMNS )
|
||||
printf("%10ld\n",rl->r_val.rel_i) ;
|
||||
else printf("\n") ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
||||
337
util/ass/ass70.c
337
util/ass/ass70.c
@@ -1,337 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ass00.h"
|
||||
#include "assex.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** utilities of EM1-assembler/loader
|
||||
*/
|
||||
|
||||
static int globstep;
|
||||
|
||||
/*
|
||||
* glohash returns an index in table and leaves a stepsize in globstep
|
||||
*
|
||||
*/
|
||||
|
||||
static int glohash(aname,size) char *aname; {
|
||||
register char *p;
|
||||
register i;
|
||||
register sum;
|
||||
|
||||
/*
|
||||
* Computes a hash-value from a string.
|
||||
* Algorithm is adding all the characters after shifting some way.
|
||||
*/
|
||||
|
||||
for(sum=i=0,p=aname;*p;i += 3)
|
||||
sum += (*p++)<<(i&07);
|
||||
sum &= 077777;
|
||||
globstep = (sum / size) % (size - 7) + 7;
|
||||
return(sum % size);
|
||||
}
|
||||
|
||||
/*
|
||||
* lookup idname in labeltable , if it is not there enter it
|
||||
* return index in labeltable
|
||||
*/
|
||||
|
||||
glob_t *glo2lookup(name,status) char *name; {
|
||||
|
||||
return(glolookup(name,status,mglobs,oursize->n_mlab));
|
||||
}
|
||||
|
||||
glob_t *xglolookup(name,status) char *name; {
|
||||
|
||||
return(glolookup(name,status,xglobs,oursize->n_glab));
|
||||
}
|
||||
|
||||
static void findext(g) glob_t *g ; {
|
||||
glob_t *x;
|
||||
|
||||
x = xglolookup(g->g_name,ENTERING);
|
||||
if (x && (x->g_status&DEF)) {
|
||||
g->g_status |= DEF;
|
||||
g->g_val.g_addr = x->g_val.g_addr;
|
||||
}
|
||||
g->g_status |= EXT;
|
||||
}
|
||||
|
||||
glob_t *glolookup(name,status,table,size)
|
||||
char *name; /* name */
|
||||
int status; /* kind of lookup */
|
||||
glob_t *table; /* which table to use */
|
||||
int size; /* size for hash */
|
||||
{
|
||||
register glob_t *g;
|
||||
register rem,j;
|
||||
int new;
|
||||
|
||||
/*
|
||||
* lookup global symbol name in specified table.
|
||||
* Various actions are taken depending on status.
|
||||
*
|
||||
* DEFINING:
|
||||
* Lookup or enter the symbol, check for mult. def.
|
||||
* OCCURRING:
|
||||
* Lookup the symbol, export if not known.
|
||||
* INTERNING:
|
||||
* Enter symbol local to the module.
|
||||
* EXTERNING:
|
||||
* Enter symbol visable from every module.
|
||||
* SEARCHING:
|
||||
* Lookup the symbol, return 0 if not found.
|
||||
* ENTERING:
|
||||
* Lookup or enter the symbol, don't check
|
||||
*/
|
||||
|
||||
rem = glohash(name,size);
|
||||
j = 0; new=0;
|
||||
g = &table[rem];
|
||||
while (g->g_name != 0 && strcmp(name,g->g_name) != 0) {
|
||||
j++;
|
||||
if (j>size)
|
||||
fatal("global label table overflow");
|
||||
rem = (rem + globstep) % size;
|
||||
g = &table[rem];
|
||||
}
|
||||
if (g->g_name == 0) {
|
||||
/*
|
||||
* This symbol is shining new.
|
||||
* Enter it in table except for status = SEARCHING
|
||||
*/
|
||||
if (status == SEARCHING)
|
||||
return(0);
|
||||
g->g_name = (char *) getarea((unsigned) (strlen(name) + 1));
|
||||
strcpy(g->g_name,name);
|
||||
g->g_status = 0;
|
||||
g->g_val.g_addr=0;
|
||||
new++;
|
||||
}
|
||||
switch(status) {
|
||||
case SEARCHING: /* nothing special */
|
||||
case ENTERING:
|
||||
break;
|
||||
case INTERNING:
|
||||
if (!new && (g->g_status&EXT))
|
||||
werror("INA must be first occurrence of '%s'",name);
|
||||
break;
|
||||
case EXTERNING: /* lookup in other table */
|
||||
/*
|
||||
* The If statement is removed to be friendly
|
||||
* to Backend writers having to deal with assemblers
|
||||
* not following our conventions.
|
||||
if (!new)
|
||||
error("EXA must be first occurrence of '%s'",name);
|
||||
*/
|
||||
findext(g);
|
||||
break;
|
||||
case DEFINING: /* Thou shalt not redefine */
|
||||
if (g->g_status&DEF)
|
||||
error("global symbol '%s' redefined",name);
|
||||
g->g_status |= DEF;
|
||||
break;
|
||||
case OCCURRING:
|
||||
if ( new )
|
||||
findext(g);
|
||||
g->g_status |= OCC;
|
||||
break;
|
||||
default:
|
||||
fatal("bad status in glolookup");
|
||||
}
|
||||
return(g);
|
||||
}
|
||||
|
||||
locl_t *loclookup(an,status) {
|
||||
register locl_t *lbp,*l_lbp;
|
||||
register unsigned num;
|
||||
char hinum;
|
||||
|
||||
if ( !pstate.s_locl ) fatal("label outside procedure");
|
||||
num = an;
|
||||
if ( num/LOCLABSIZE>255 ) fatal("local label number too large");
|
||||
hinum = num/LOCLABSIZE;
|
||||
l_lbp= lbp= &(*pstate.s_locl)[num%LOCLABSIZE];
|
||||
if ( lbp->l_defined==EMPTY ) {
|
||||
lbp= lbp_cast 0 ;
|
||||
} else {
|
||||
while ( lbp!= lbp_cast 0 && lbp->l_hinum != hinum ) {
|
||||
l_lbp = lbp ;
|
||||
lbp = lbp->l_chain;
|
||||
}
|
||||
}
|
||||
if ( lbp == lbp_cast 0 ) {
|
||||
if ( l_lbp->l_defined!=EMPTY ) {
|
||||
lbp = lbp_cast getarea(sizeof *lbp);
|
||||
l_lbp->l_chain= lbp ;
|
||||
} else lbp= l_lbp ;
|
||||
lbp->l_chain= lbp_cast 0 ;
|
||||
lbp->l_hinum=hinum;
|
||||
lbp->l_defined = (status==OCCURRING ? NO : YES);
|
||||
lbp->l_min= line_num;
|
||||
} else
|
||||
if (status == DEFINING) {
|
||||
if (lbp->l_defined == YES)
|
||||
error("multiple defined local symbol");
|
||||
else
|
||||
lbp->l_defined = YES;
|
||||
}
|
||||
if ( status==DEFINING ) lbp->l_min= line_num ;
|
||||
return(lbp);
|
||||
}
|
||||
|
||||
proc_t *prolookup(name,status) char *name; {
|
||||
register proc_t *p;
|
||||
register pstat;
|
||||
|
||||
/*
|
||||
* Look up a procedure name according to status
|
||||
*
|
||||
* PRO_OCC: Occurrence
|
||||
* Search both tables, local table first.
|
||||
* If not found, enter in global table
|
||||
* PRO_INT: INP
|
||||
* Enter symbol in local table.
|
||||
* PRO_DEF: Definition
|
||||
* Define local procedure.
|
||||
* PRO_EXT: EXP
|
||||
* Enter symbol in global table.
|
||||
*
|
||||
* The EXT bit in this table indicates the the name is used
|
||||
* as external in this module.
|
||||
*/
|
||||
|
||||
switch(status) {
|
||||
case PRO_OCC:
|
||||
p = searchproc(name,mprocs,oursize->n_mproc);
|
||||
if (p->p_name) {
|
||||
p->p_status |= OCC;
|
||||
return(p);
|
||||
}
|
||||
p = searchproc(name,xprocs,oursize->n_xproc);
|
||||
if (p->p_name) {
|
||||
p->p_status |= OCC;
|
||||
return(p);
|
||||
}
|
||||
pstat = OCC|EXT;
|
||||
unresolved++ ;
|
||||
break;
|
||||
case PRO_INT:
|
||||
p = searchproc(name,xprocs,oursize->n_xproc);
|
||||
if (p->p_name && (p->p_status&EXT) )
|
||||
error("pro '%s' conflicting use",name);
|
||||
|
||||
p = searchproc(name,mprocs,oursize->n_mproc);
|
||||
if (p->p_name)
|
||||
werror("INP must be first occurrence of '%s'",name);
|
||||
pstat = 0;
|
||||
break;
|
||||
case PRO_EXT:
|
||||
p = searchproc(name,mprocs,oursize->n_mproc);
|
||||
if (p->p_name)
|
||||
error("pro '%s' exists already localy",name);
|
||||
p = searchproc(name,xprocs,oursize->n_xproc);
|
||||
if (p->p_name) {
|
||||
/*
|
||||
* The If statement is removed to be friendly
|
||||
* to Backend writers having to deal with assemblers
|
||||
* not following our conventions.
|
||||
if ( p->p_status&EXT )
|
||||
werror("EXP must be first occurrence of '%s'",
|
||||
name) ;
|
||||
*/
|
||||
p->p_status |= EXT;
|
||||
return(p);
|
||||
}
|
||||
pstat = EXT;
|
||||
unresolved++;
|
||||
break;
|
||||
case PRO_DEF:
|
||||
p = searchproc(name,xprocs,oursize->n_xproc);
|
||||
if (p->p_name && (p->p_status&EXT) ) {
|
||||
if (p->p_status&DEF)
|
||||
error("global pro '%s' redeclared",name);
|
||||
else
|
||||
unresolved-- ;
|
||||
p->p_status |= DEF;
|
||||
return(p);
|
||||
} else {
|
||||
p = searchproc(name,mprocs,oursize->n_mproc);
|
||||
if (p->p_name) {
|
||||
if (p->p_status&DEF)
|
||||
error("local pro '%s' redeclared",
|
||||
name);
|
||||
p->p_status |= DEF;
|
||||
return(p);
|
||||
}
|
||||
}
|
||||
pstat = DEF;
|
||||
break;
|
||||
default:
|
||||
fatal("bad status in prolookup");
|
||||
}
|
||||
return(enterproc(name,pstat,p));
|
||||
}
|
||||
|
||||
proc_t *searchproc(name,table,size)
|
||||
char *name;
|
||||
proc_t *table;
|
||||
int size;
|
||||
{
|
||||
register proc_t *p;
|
||||
register rem,j;
|
||||
|
||||
/*
|
||||
* return a pointer into table to the place where the procedure
|
||||
* name is or should be if in the table.
|
||||
*/
|
||||
|
||||
rem = glohash(name,size);
|
||||
j = 0;
|
||||
p = &table[rem];
|
||||
while (p->p_name != 0 && strcmp(name,p->p_name) != 0) {
|
||||
j++;
|
||||
if (j>size)
|
||||
fatal("procedure table overflow");
|
||||
rem = (rem + globstep) % size;
|
||||
p = &table[rem];
|
||||
}
|
||||
return(p);
|
||||
}
|
||||
|
||||
proc_t *enterproc(name,status,place)
|
||||
char *name;
|
||||
char status;
|
||||
proc_t *place; {
|
||||
register proc_t *p;
|
||||
|
||||
/*
|
||||
* Enter the procedure name into the table at place place.
|
||||
* Place had better be computed by searchproc().
|
||||
*
|
||||
* NOTE:
|
||||
* At this point the procedure gets assigned a number.
|
||||
* This number is used as a parameter of cal and in some
|
||||
* other ways. There exists a 1-1 correspondence between
|
||||
* procedures and numbers.
|
||||
* Two local procedures with the same name in different
|
||||
* modules have different numbers.
|
||||
*/
|
||||
|
||||
p=place;
|
||||
p->p_name = (char *) getarea((unsigned) (strlen(name) + 1));
|
||||
strcpy(p->p_name,name);
|
||||
p->p_status = status;
|
||||
if (procnum>=oursize->n_proc)
|
||||
fatal("too many procedures");
|
||||
p->p_num = procnum++;
|
||||
return(p);
|
||||
}
|
||||
413
util/ass/ass80.c
413
util/ass/ass80.c
@@ -1,413 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ass00.h"
|
||||
#include "assex.h"
|
||||
#include <em_path.h>
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* this file contains several library routines.
|
||||
*/
|
||||
|
||||
zero(area,length) char *area; unsigned length ; {
|
||||
register char *p;
|
||||
register n;
|
||||
/*
|
||||
* Clear area of length bytes.
|
||||
*/
|
||||
if ((n=length)==0)
|
||||
return;
|
||||
p = area;
|
||||
do *p++=0; while (--n);
|
||||
}
|
||||
|
||||
/* VARARGS1 */
|
||||
static void pr_error(string1,a1,a2,a3,a4) char *string1 ; {
|
||||
/*
|
||||
* diagnostic output
|
||||
*/
|
||||
fprintf(stderr,"%s: ",progname);
|
||||
if (curfile) {
|
||||
fprintf(stderr,"file %s",curfile);
|
||||
if (archmode)
|
||||
fprintf(stderr," (%.14s)",archhdr.ar_name);
|
||||
fprintf(stderr,": ");
|
||||
}
|
||||
if ( pstate.s_curpro ) {
|
||||
fprintf(stderr,"proc %s, ",pstate.s_curpro->p_name);
|
||||
}
|
||||
fprintf(stderr,"line %d: ",line_num);
|
||||
fprintf(stderr,string1,a1,a2,a3,a4);
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
/* VARARGS1 */
|
||||
void error(string1,a1,a2,a3,a4) char *string1 ; {
|
||||
pr_error(string1,a1,a2,a3,a4) ;
|
||||
nerrors++ ;
|
||||
}
|
||||
|
||||
/* VARARGS1 */
|
||||
void werror(string1,a1,a2,a3,a4) char *string1 ; {
|
||||
if ( wflag ) return ;
|
||||
pr_error(string1,a1,a2,a3,a4) ;
|
||||
}
|
||||
|
||||
fatal(s) char *s; {
|
||||
/*
|
||||
* handle fatal errors
|
||||
*/
|
||||
error("Fatal error: %s",s);
|
||||
dump(0);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
#ifndef CPM
|
||||
FILE *frewind(f) FILE *f ; {
|
||||
/* Rewind a file open for writing and open it for reading */
|
||||
/* Assumption, file descriptor is r/w */
|
||||
register FILE *tmp ;
|
||||
tmp=fdopen(dup(fileno(f)),"r");
|
||||
fclose(f);
|
||||
rewind(tmp);
|
||||
return tmp ;
|
||||
}
|
||||
#endif
|
||||
|
||||
int xgetc(af) register FILE *af; {
|
||||
register int nextc;
|
||||
/*
|
||||
* read next character; fatal if there isn't one
|
||||
*/
|
||||
nextc=fgetc(af) ;
|
||||
if ( feof(af) )
|
||||
fatal("unexpected end of file");
|
||||
return nextc ;
|
||||
}
|
||||
|
||||
xputc(c,af) register FILE *af; {
|
||||
/* output one character and scream if it gives an error */
|
||||
fputc(c,af) ;
|
||||
if ( ferror(af) ) fatal("write error") ;
|
||||
}
|
||||
|
||||
|
||||
putblk(stream,from,amount)
|
||||
register FILE *stream; register char *from ; register int amount ; {
|
||||
|
||||
for ( ; amount-- ; from++ ) {
|
||||
fputc(*from,stream) ;
|
||||
if ( ferror(stream) ) fatal("write error") ;
|
||||
}
|
||||
}
|
||||
|
||||
int getblk(stream,from,amount)
|
||||
register FILE *stream; register char *from ; register int amount ; {
|
||||
|
||||
for ( ; amount-- ; from++ ) {
|
||||
*from = fgetc(stream) ;
|
||||
if ( feof(stream) ) return 1 ;
|
||||
}
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
xput16(w,f) FILE *f; {
|
||||
/*
|
||||
* two times xputc
|
||||
*/
|
||||
xputc(w,f);
|
||||
xputc(w>>8,f);
|
||||
}
|
||||
|
||||
xputarb(l,w,f) int l ; cons_t w ; FILE *f ; {
|
||||
while ( l-- ) {
|
||||
xputc( int_cast w,f) ;
|
||||
w >>=8 ;
|
||||
}
|
||||
}
|
||||
|
||||
put8(n) {
|
||||
xputc(n,tfile);
|
||||
textoff++;
|
||||
}
|
||||
|
||||
put16(n) {
|
||||
/*
|
||||
* note reversed order of bytes.
|
||||
* this is done for faster interpretation.
|
||||
*/
|
||||
xputc(n>>8,tfile);
|
||||
xputc(n&0377,tfile);
|
||||
textoff += 2;
|
||||
}
|
||||
|
||||
put32(n) cons_t n ; {
|
||||
put16( int_cast (n>>16)) ;
|
||||
put16( int_cast n) ;
|
||||
}
|
||||
|
||||
put64(n) cons_t n ; {
|
||||
fatal("put64 called") ;
|
||||
}
|
||||
|
||||
int xget8() {
|
||||
/*
|
||||
* Read one byte from ifile.
|
||||
*/
|
||||
if (libeof && inpoff >= libeof)
|
||||
return EOF ;
|
||||
inpoff++;
|
||||
return fgetc(ifile) ;
|
||||
}
|
||||
|
||||
unsigned get8() {
|
||||
register int nextc;
|
||||
/*
|
||||
* Read one byte from ifile.
|
||||
*/
|
||||
nextc=xget8();
|
||||
if ( nextc==EOF ) {
|
||||
if (libeof)
|
||||
fatal("Tried to read past end of arentry\n");
|
||||
else
|
||||
fatal("end of file on input");
|
||||
}
|
||||
return nextc ;
|
||||
}
|
||||
|
||||
cons_t xgetarb(l,f) int l; FILE *f ; {
|
||||
cons_t val ;
|
||||
register int shift ;
|
||||
int c;
|
||||
|
||||
shift=0 ; val=0 ;
|
||||
while ( l-- ) {
|
||||
val += ((cons_t)(c = ctrunc(xgetc(f))))<<shift ;
|
||||
shift += 8 ;
|
||||
}
|
||||
if (c == 0377 && shift > 8 && ((shift>>3)&1)) {
|
||||
while (shift < 8*sizeof(cons_t)) {
|
||||
val += ((cons_t)c)<<shift ;
|
||||
shift += 8;
|
||||
}
|
||||
}
|
||||
return val ;
|
||||
}
|
||||
|
||||
ext8(b) {
|
||||
/*
|
||||
* Handle one byte of data.
|
||||
*/
|
||||
++dataoff;
|
||||
xputc(b,dfile);
|
||||
}
|
||||
|
||||
extword(w) cons_t w ; {
|
||||
/* Assemble the word constant w.
|
||||
* NOTE: The bytes are written low to high.
|
||||
*/
|
||||
register i ;
|
||||
for ( i=wordsize ; i-- ; ) {
|
||||
ext8( int_cast w) ;
|
||||
w >>= 8 ;
|
||||
}
|
||||
}
|
||||
|
||||
extarb(size,value) int size ; long value ; {
|
||||
/* Assemble the 'size' constant value.
|
||||
* The bytes are again written low to high.
|
||||
*/
|
||||
register i ;
|
||||
for ( i=size ; i-- ; ) {
|
||||
ext8( int_cast value ) ;
|
||||
value >>=8 ;
|
||||
}
|
||||
}
|
||||
|
||||
extadr(a) cons_t a ; {
|
||||
/* Assemble the word constant a.
|
||||
* NOTE: The bytes are written low to high.
|
||||
*/
|
||||
register i ;
|
||||
for ( i=ptrsize ; i-- ; ) {
|
||||
ext8( int_cast a) ;
|
||||
a >>= 8 ;
|
||||
}
|
||||
}
|
||||
|
||||
xputa(a,f) cons_t a ; FILE *f ; {
|
||||
/* Assemble the pointer constant a.
|
||||
* NOTE: The bytes are written low to high.
|
||||
*/
|
||||
register i ;
|
||||
for ( i=ptrsize ; i-- ; ) {
|
||||
xputc( int_cast a,f) ;
|
||||
a >>= 8 ;
|
||||
}
|
||||
}
|
||||
|
||||
cons_t xgeta(f) FILE *f ; {
|
||||
/* Read the pointer constant a.
|
||||
* NOTE: The bytes were written low to high.
|
||||
*/
|
||||
register i, shift ;
|
||||
cons_t val ;
|
||||
val = 0 ; shift=0 ;
|
||||
for ( i=ptrsize ; i-- ; ) {
|
||||
val += ((cons_t)xgetc(f))<<shift ;
|
||||
shift += 8 ;
|
||||
}
|
||||
return val ;
|
||||
}
|
||||
|
||||
int icount(size) {
|
||||
int amount ;
|
||||
amount=(dataoff-lastoff)/size ;
|
||||
if ( amount>MAXBYTE) fatal("Descriptor overflow");
|
||||
return amount ;
|
||||
}
|
||||
|
||||
setmode(mode) {
|
||||
|
||||
if (datamode==mode) { /* in right mode already */
|
||||
switch ( datamode ) {
|
||||
case DATA_CONST:
|
||||
if ( (dataoff-lastoff)/wordsize < MAXBYTE ) return ;
|
||||
break ;
|
||||
case DATA_BYTES:
|
||||
if ( dataoff-lastoff < MAXBYTE ) return ;
|
||||
break ;
|
||||
case DATA_IPTR:
|
||||
case DATA_DPTR:
|
||||
if ( (dataoff-lastoff)/ptrsize < MAXBYTE ) return ;
|
||||
break ;
|
||||
case DATA_ICON:
|
||||
case DATA_FCON:
|
||||
case DATA_UCON:
|
||||
case DATA_BSS:
|
||||
break ;
|
||||
default:
|
||||
return ;
|
||||
}
|
||||
setmode(DATA_NUL) ; /* flush current descriptor */
|
||||
setmode(mode) ;
|
||||
return;
|
||||
}
|
||||
switch(datamode) { /* terminate current mode */
|
||||
case DATA_NUL:
|
||||
break; /* nothing to terminate */
|
||||
case DATA_CONST:
|
||||
lastheader->r_val.rel_i=icount(wordsize) ;
|
||||
lastheader->r_typ = RELHEAD;
|
||||
datablocks++;
|
||||
break;
|
||||
case DATA_BYTES:
|
||||
lastheader->r_val.rel_i=icount(1) ;
|
||||
lastheader->r_typ = RELHEAD;
|
||||
datablocks++;
|
||||
break;
|
||||
case DATA_DPTR:
|
||||
case DATA_IPTR:
|
||||
lastheader->r_val.rel_i=icount(ptrsize) ;
|
||||
lastheader->r_typ = RELHEAD;
|
||||
datablocks++;
|
||||
break;
|
||||
default:
|
||||
datablocks++;
|
||||
break;
|
||||
}
|
||||
datamode=mode;
|
||||
switch(datamode) {
|
||||
case DATA_NUL:
|
||||
break;
|
||||
case DATA_CONST:
|
||||
ext8(HEADCONST);
|
||||
lastheader=data_reloc( chp_cast 0,dataoff,RELNULL);
|
||||
ext8(0);
|
||||
lastoff=dataoff;
|
||||
break;
|
||||
case DATA_BYTES:
|
||||
ext8(HEADBYTE);
|
||||
lastheader=data_reloc( chp_cast 0,dataoff,RELNULL);
|
||||
ext8(0);
|
||||
lastoff=dataoff;
|
||||
break;
|
||||
case DATA_IPTR:
|
||||
ext8(HEADIPTR);
|
||||
lastheader=data_reloc( chp_cast 0,dataoff,RELNULL);
|
||||
ext8(0);
|
||||
lastoff=dataoff;
|
||||
break;
|
||||
case DATA_DPTR:
|
||||
ext8(HEADDPTR);
|
||||
lastheader=data_reloc( chp_cast 0,dataoff,RELNULL);
|
||||
ext8(0);
|
||||
lastoff=dataoff;
|
||||
break;
|
||||
case DATA_ICON:
|
||||
ext8(HEADICON) ;
|
||||
ext8( int_cast consiz) ;
|
||||
break;
|
||||
case DATA_FCON:
|
||||
ext8(HEADFCON) ;
|
||||
ext8( int_cast consiz) ;
|
||||
break;
|
||||
case DATA_UCON:
|
||||
ext8(HEADUCON) ;
|
||||
ext8( int_cast consiz) ;
|
||||
break;
|
||||
case DATA_REP:
|
||||
ext8(HEADREP) ;
|
||||
break ;
|
||||
case DATA_BSS:
|
||||
ext8(HEADBSS) ;
|
||||
break;
|
||||
default:
|
||||
fatal("Unknown mode in setmode") ;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CPM
|
||||
int tmpfil() {
|
||||
register char *fname, *cpname ;
|
||||
static char sfname[] = "tmp.00000";
|
||||
register fildes,pid;
|
||||
static char name[80] = TMP_DIR ;
|
||||
int count;
|
||||
/*
|
||||
* This procedure returns a file-descriptor of a temporary
|
||||
* file valid for reading and writing.
|
||||
* After closing the tmpfil-descriptor the file is lost
|
||||
* Calling this routine frees the program from generating uniqe names.
|
||||
*/
|
||||
fname = sfname+4;
|
||||
count = 10;
|
||||
pid = getpid();
|
||||
while (pid!=0) {
|
||||
*fname++ = (pid&07) + '0';
|
||||
pid >>= 3;
|
||||
}
|
||||
*fname = 0;
|
||||
for ( fname=name ; *fname ; fname++ ) ;
|
||||
cpname=sfname ;
|
||||
while ( *fname++ = *cpname++ ) ;
|
||||
do {
|
||||
fname = name;
|
||||
if ((fildes = creat(fname, 0600)) < 0)
|
||||
if ((fildes = creat(fname=sfname, 0600)) < 0)
|
||||
return(-1);
|
||||
if (close(fildes) < 0)
|
||||
;
|
||||
} while((fildes = open(fname, 2)) < 0 && count--);
|
||||
if (unlink(fname) < 0)
|
||||
;
|
||||
return(fildes);
|
||||
}
|
||||
#endif
|
||||
864
util/ass/assci.c
864
util/ass/assci.c
@@ -1,864 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ass00.h"
|
||||
#include "assex.h"
|
||||
#include <em_mes.h>
|
||||
#include <em_pseu.h>
|
||||
#include <em_ptyp.h>
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* read compact code and fill in tables
|
||||
*/
|
||||
|
||||
static int tabval;
|
||||
static cons_t argval;
|
||||
|
||||
static int oksizes; /* MES EMX,.,. seen */
|
||||
|
||||
static enum m_type { CON, ROM, HOLBSS } memtype ;
|
||||
static int valtype; /* Transfer of type information between
|
||||
valsize, inpseudo and putval
|
||||
*/
|
||||
|
||||
int table3(i) {
|
||||
|
||||
switch(i) {
|
||||
case sp_ilb1:
|
||||
tabval = get8();
|
||||
break;
|
||||
case sp_dlb1:
|
||||
make_string(get8());
|
||||
i= sp_dnam;
|
||||
break;
|
||||
case sp_dlb2:
|
||||
tabval = get16();
|
||||
if ( tabval<0 ) {
|
||||
error("illegal data label .%d",tabval);
|
||||
tabval=0 ;
|
||||
}
|
||||
make_string(tabval);
|
||||
i= sp_dnam;
|
||||
break;
|
||||
case sp_cst2:
|
||||
argval = get16();
|
||||
break;
|
||||
case sp_ilb2:
|
||||
tabval = get16();
|
||||
if ( tabval<0 ) {
|
||||
error("illegal instruction label %d",tabval);
|
||||
tabval=0 ;
|
||||
}
|
||||
i = sp_ilb1;
|
||||
break;
|
||||
case sp_cst4:
|
||||
i = sp_cst2;
|
||||
argval = get32();
|
||||
break;
|
||||
case sp_dnam:
|
||||
case sp_pnam:
|
||||
inident();
|
||||
break ;
|
||||
case sp_scon:
|
||||
getstring() ;
|
||||
break;
|
||||
case sp_doff:
|
||||
getarg(sym_ptyp);
|
||||
getarg(cst_ptyp);
|
||||
break;
|
||||
case sp_icon:
|
||||
case sp_ucon:
|
||||
case sp_fcon:
|
||||
getarg(cst_ptyp);
|
||||
consiz = argval;
|
||||
if ( consiz<wordsize ?
|
||||
wordsize%consiz!=0 : consiz%wordsize!=0 ) {
|
||||
fatal("illegal object size") ;
|
||||
}
|
||||
getstring();
|
||||
break;
|
||||
}
|
||||
return(i);
|
||||
}
|
||||
|
||||
int get16() {
|
||||
register int l_byte, h_byte;
|
||||
|
||||
l_byte = get8();
|
||||
h_byte = get8();
|
||||
if ( h_byte>=128 ) h_byte -= 256 ;
|
||||
return l_byte | (h_byte*256) ;
|
||||
}
|
||||
|
||||
int getu16() {
|
||||
register int l_byte, h_byte;
|
||||
|
||||
l_byte = get8();
|
||||
h_byte = get8();
|
||||
return l_byte | (h_byte*256) ;
|
||||
}
|
||||
|
||||
cons_t get32() {
|
||||
register cons_t l;
|
||||
register int h_byte;
|
||||
|
||||
l = get8(); l |= (unsigned)get8()*256 ; l |= get8()*256L*256L ;
|
||||
h_byte = get8() ;
|
||||
if ( h_byte>=128 ) h_byte -= 256 ;
|
||||
return l | (h_byte*256L*256*256L) ;
|
||||
}
|
||||
|
||||
int table1() {
|
||||
register i;
|
||||
|
||||
i = xget8();
|
||||
if (i < sp_fmnem+sp_nmnem && i >= sp_fmnem) {
|
||||
tabval = i-sp_fmnem;
|
||||
return(sp_fmnem);
|
||||
}
|
||||
if (i < sp_fpseu+sp_npseu && i >= sp_fpseu) {
|
||||
tabval = i;
|
||||
return(sp_fpseu);
|
||||
}
|
||||
if (i < sp_filb0+sp_nilb0 && i >= sp_filb0) {
|
||||
tabval = i - sp_filb0;
|
||||
return(sp_ilb1);
|
||||
}
|
||||
return(table3(i));
|
||||
}
|
||||
|
||||
int table2() {
|
||||
register i;
|
||||
|
||||
i = get8();
|
||||
if (i < sp_fcst0+sp_ncst0 && i >= sp_fcst0) {
|
||||
argval = i - sp_zcst0;
|
||||
return(sp_cst2);
|
||||
}
|
||||
return(table3(i));
|
||||
}
|
||||
|
||||
int getarg(typset) {
|
||||
register t,argtyp;
|
||||
|
||||
argtyp = t = table2();
|
||||
t -= sp_fspec;
|
||||
t = 1 << t;
|
||||
if ((typset & t) == 0)
|
||||
error("bad argument type %d",argtyp);
|
||||
return(argtyp);
|
||||
}
|
||||
|
||||
cons_t getint() {
|
||||
getarg(cst_ptyp);
|
||||
return(argval);
|
||||
}
|
||||
|
||||
glob_t *getlab(status) {
|
||||
getarg(sym_ptyp);
|
||||
return(glo2lookup(string,status));
|
||||
}
|
||||
|
||||
char *getdig(str,number) char *str; register unsigned number; {
|
||||
register int remain;
|
||||
|
||||
remain= number%10;
|
||||
number /= 10;
|
||||
if ( number ) str= getdig(str,number) ;
|
||||
*str++ = '0'+remain ;
|
||||
return str ;
|
||||
}
|
||||
|
||||
make_string(n) unsigned n ; {
|
||||
string[0] = '.';
|
||||
*getdig(&string[1],n)= 0;
|
||||
}
|
||||
|
||||
|
||||
getstring() {
|
||||
register char *p;
|
||||
register n;
|
||||
|
||||
getarg(cst_ptyp);
|
||||
if ( argval < 0 || argval >= MAXSTRING-1 )
|
||||
fatal("string/identifier too long");
|
||||
strlngth = n = argval;
|
||||
p = string;
|
||||
while (--n >= 0)
|
||||
*p++ = get8();
|
||||
*p = 0 ;
|
||||
}
|
||||
|
||||
inident() {
|
||||
getstring();
|
||||
}
|
||||
|
||||
char *inproname() {
|
||||
getarg(ptyp(sp_pnam));
|
||||
return(string);
|
||||
}
|
||||
|
||||
int needed() {
|
||||
register glob_t *g;
|
||||
register proc_t *p;
|
||||
|
||||
for(;;){
|
||||
switch ( table2() ) {
|
||||
case sp_dnam :
|
||||
if (g = xglolookup(string,SEARCHING)) {
|
||||
if ((g->g_status&DEF) != 0)
|
||||
continue ;
|
||||
} else continue ;
|
||||
break ;
|
||||
case sp_pnam :
|
||||
p = searchproc(string,xprocs,oursize->n_xproc);
|
||||
if (p->p_name) {
|
||||
if ((p->p_status & DEF) != 0)
|
||||
continue ;
|
||||
} else continue ;
|
||||
break ;
|
||||
default :
|
||||
error("Unexpected byte after ms_ext") ;
|
||||
case sp_cend :
|
||||
return FALSE ;
|
||||
}
|
||||
while ( table2()!=sp_cend ) ;
|
||||
return TRUE ;
|
||||
}
|
||||
}
|
||||
|
||||
cons_t valsize() {
|
||||
switch(valtype=table2()) { /* valtype is used by putval and inpseudo */
|
||||
case sp_cst2:
|
||||
return wordsize ;
|
||||
case sp_ilb1:
|
||||
case sp_dnam:
|
||||
case sp_doff:
|
||||
case sp_pnam:
|
||||
return ptrsize ;
|
||||
case sp_scon:
|
||||
return strlngth ;
|
||||
case sp_fcon:
|
||||
case sp_icon:
|
||||
case sp_ucon:
|
||||
return consiz ;
|
||||
case sp_cend:
|
||||
return 0 ;
|
||||
default:
|
||||
fatal("value expected") ;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
newline(type) {
|
||||
register line_t *n_lnp ;
|
||||
|
||||
if ( type>VALLOW ) type=VALLOW ;
|
||||
n_lnp = lnp_cast getarea((unsigned)linesize[type]) ;
|
||||
n_lnp->l_next = pstate.s_fline ;
|
||||
pstate.s_fline = n_lnp ;
|
||||
n_lnp->type1 = type ;
|
||||
n_lnp->opoff = NO_OFF ;
|
||||
}
|
||||
|
||||
read_compact() {
|
||||
|
||||
/*
|
||||
* read module in compact EM1 code
|
||||
*/
|
||||
init_module();
|
||||
pass = 1;
|
||||
eof_seen = 0;
|
||||
do {
|
||||
compact_line() ;
|
||||
line_num++;
|
||||
} while (!eof_seen) ;
|
||||
endproc() ; /* Throw away unwanted garbage */
|
||||
if ( mod_sizes ) end_module();
|
||||
/* mod_sizes is only false for rejected library modules */
|
||||
}
|
||||
|
||||
int compact_line() {
|
||||
register instr_no ;
|
||||
|
||||
/*
|
||||
* read one "line" of compact code.
|
||||
*/
|
||||
curglosym=0;
|
||||
switch (table1()) {
|
||||
default:
|
||||
fatal("unknown byte at start of \"line\""); /* NOTREACHED */
|
||||
case EOF:
|
||||
eof_seen++ ;
|
||||
while ( pstate.s_prevstat != pst_cast 0 ) {
|
||||
error("missing end") ; do_proc() ;
|
||||
}
|
||||
return ;
|
||||
case sp_fmnem:
|
||||
if ( pstate.s_curpro == prp_cast 0) {
|
||||
error("instruction outside procedure");
|
||||
}
|
||||
instr_no = tabval;
|
||||
if ( (em_flag[instr_no]&EM_PAR)==PAR_NO ) {
|
||||
newline(MISSING) ;
|
||||
pstate.s_fline->instr_num= instr_no ;
|
||||
return ;
|
||||
}
|
||||
/*
|
||||
* This instruction should have an opcode, so read it after
|
||||
* this switch.
|
||||
*/
|
||||
break;
|
||||
case sp_dnam:
|
||||
chkstart() ;
|
||||
align(wordsize) ;
|
||||
curglosym = glo2lookup(string,DEFINING);
|
||||
curglosym->g_val.g_addr = databytes;
|
||||
lastglosym = curglosym;
|
||||
setline() ; line_num++ ;
|
||||
if (table1() != sp_fpseu)
|
||||
fatal("no pseudo after data label");
|
||||
case sp_fpseu:
|
||||
inpseudo(tabval);
|
||||
setline() ;
|
||||
return ;
|
||||
case sp_ilb1:
|
||||
newline(LOCSYM) ;
|
||||
pstate.s_fline->ad.ad_lp = loclookup(tabval,DEFINING);
|
||||
pstate.s_fline->instr_num = sp_ilb1;
|
||||
return ;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now process argument
|
||||
*/
|
||||
|
||||
switch(table2()) {
|
||||
default:
|
||||
fatal("unknown byte at start of argument"); /*NOTREACHED*/
|
||||
case sp_cst2:
|
||||
if ( (em_flag[instr_no]&EM_PAR)==PAR_B ) {
|
||||
/* value indicates a label */
|
||||
newline(LOCSYM) ;
|
||||
pstate.s_fline->ad.ad_lp=
|
||||
loclookup((int)argval,OCCURRING) ;
|
||||
} else {
|
||||
if ( argval>=VAL1(VALLOW) && argval<=VAL1(VALHIGH)) {
|
||||
newline(VALLOW) ;
|
||||
pstate.s_fline->type1 = argval+VALMID ;
|
||||
} else {
|
||||
newline(CONST) ;
|
||||
pstate.s_fline->ad.ad_i = argval;
|
||||
pstate.s_fline->type1 = CONST;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case sp_ilb1:
|
||||
newline(LOCSYM) ;
|
||||
pstate.s_fline->ad.ad_lp = loclookup(tabval,OCCURRING);
|
||||
break;
|
||||
case sp_dnam:
|
||||
newline(GLOSYM) ;
|
||||
pstate.s_fline->ad.ad_gp = glo2lookup(string,OCCURRING);
|
||||
break;
|
||||
case sp_pnam:
|
||||
newline(PROCNAME) ;
|
||||
pstate.s_fline->ad.ad_pp=prolookup(string,PRO_OCC);
|
||||
break;
|
||||
case sp_cend:
|
||||
if ( (em_flag[instr_no]&EM_PAR)!=PAR_W ) {
|
||||
fatal("missing operand") ;
|
||||
}
|
||||
newline(MISSING) ;
|
||||
break ;
|
||||
case sp_doff:
|
||||
newline(GLOOFF) ;
|
||||
pstate.s_fline->ad.ad_df.df_i = argval ;
|
||||
pstate.s_fline->ad.ad_df.df_gp= glo2lookup(string,OCCURRING) ;
|
||||
break ;
|
||||
}
|
||||
pstate.s_fline->instr_num= instr_no ;
|
||||
return ;
|
||||
}
|
||||
|
||||
inpseudo(instr_no) {
|
||||
cons_t cst;
|
||||
register proc_t *prptr;
|
||||
cons_t objsize;
|
||||
cons_t par1,par2;
|
||||
register char *pars;
|
||||
|
||||
/*
|
||||
* get operands of pseudo (if needed) and process it.
|
||||
*/
|
||||
|
||||
switch ( ctrunc(instr_no) ) {
|
||||
case ps_bss:
|
||||
chkstart() ;
|
||||
typealign(HOLBSS) ;
|
||||
cst = getint(); /* number of bytes */
|
||||
extbss(cst);
|
||||
break;
|
||||
case ps_hol:
|
||||
chkstart() ;
|
||||
typealign(HOLBSS) ;
|
||||
holsize=getint();
|
||||
holbase=databytes;
|
||||
extbss(holsize);
|
||||
break;
|
||||
case ps_rom:
|
||||
case ps_con:
|
||||
chkstart() ;
|
||||
typealign( ctrunc(instr_no)==ps_rom ? ROM : CON ) ;
|
||||
while( (objsize=valsize())!=0 ) {
|
||||
if ( valtype!=sp_scon) sizealign(objsize) ;
|
||||
putval() ;
|
||||
databytes+=objsize ;
|
||||
}
|
||||
break;
|
||||
case ps_end:
|
||||
prptr= pstate.s_curpro ;
|
||||
if ( prptr == prp_cast 0 ) fatal("unexpected END") ;
|
||||
proctab[prptr->p_num].pr_off = textbytes;
|
||||
if (procflag) {
|
||||
printf("%6lu\t%6lo\t%5d\t%-12s\t%s",
|
||||
textbytes,textbytes,
|
||||
prptr->p_num,prptr->p_name,curfile);
|
||||
if (archmode)
|
||||
printf("(%.14s)",archhdr.ar_name);
|
||||
printf("\n");
|
||||
}
|
||||
par2 = proctab[prptr->p_num].pr_loc ;
|
||||
if ( getarg(cst_ptyp|ptyp(sp_cend))==sp_cend ) {
|
||||
if ( par2 == -1 ) {
|
||||
fatal("size of local area unspecified") ;
|
||||
}
|
||||
} else {
|
||||
if ( par2 != -1 && argval!=par2 ) {
|
||||
fatal("inconsistent local area size") ;
|
||||
}
|
||||
proctab[prptr->p_num].pr_loc = argval ;
|
||||
}
|
||||
setline();
|
||||
do_proc();
|
||||
break;
|
||||
case ps_mes:
|
||||
switch( int_cast getint() ) {
|
||||
case ms_err:
|
||||
error("module with error") ; ertrap();
|
||||
/* NOTREACHED */
|
||||
case ms_emx:
|
||||
if ( oksizes ) {
|
||||
if ( wordsize!=getint() ) {
|
||||
fatal("Inconsistent word size");
|
||||
}
|
||||
if ( ptrsize!=getint() ) {
|
||||
fatal("Inconsistent pointer size");
|
||||
}
|
||||
} else {
|
||||
oksizes++ ;
|
||||
wordsize=getint();ptrsize=getint();
|
||||
if ( wordsize!=2 && wordsize!=4 ) {
|
||||
fatal("Illegal word size");
|
||||
}
|
||||
if ( ptrsize!=2 && ptrsize!=4 ) {
|
||||
fatal("Illegal pointer size");
|
||||
}
|
||||
setsizes() ;
|
||||
}
|
||||
++mod_sizes ;
|
||||
break;
|
||||
case ms_src:
|
||||
break;
|
||||
case ms_flt:
|
||||
intflags |= 020; break; /*floats used*/
|
||||
case ms_ext:
|
||||
if ( !needed() ) {
|
||||
eof_seen++ ;
|
||||
}
|
||||
if ( line_num>2 ) {
|
||||
werror("mes ms_ext must be first or second pseudo") ;
|
||||
}
|
||||
return ;
|
||||
}
|
||||
while (table2() != sp_cend)
|
||||
;
|
||||
break;
|
||||
case ps_exc:
|
||||
par1 = getint();
|
||||
par2 = getint();
|
||||
if (par1 == 0 || par2 == 0)
|
||||
break;
|
||||
exchange((int)par2,(int)par1) ;
|
||||
break;
|
||||
case ps_exa:
|
||||
getlab(EXTERNING);
|
||||
break;
|
||||
case ps_ina:
|
||||
getlab(INTERNING);
|
||||
break;
|
||||
case ps_pro:
|
||||
chkstart() ;
|
||||
initproc();
|
||||
pars = inproname();
|
||||
if ( getarg(cst_ptyp|ptyp(sp_cend))==sp_cend ) {
|
||||
par2 = -1 ;
|
||||
} else {
|
||||
par2 = argval ;
|
||||
}
|
||||
prptr = prolookup(pars,PRO_DEF);
|
||||
proctab[prptr->p_num].pr_loc = par2;
|
||||
pstate.s_curpro=prptr;
|
||||
break;
|
||||
case ps_inp:
|
||||
prptr = prolookup(inproname(),PRO_INT);
|
||||
break;
|
||||
case ps_exp:
|
||||
prptr = prolookup(inproname(),PRO_EXT);
|
||||
break;
|
||||
default:
|
||||
fatal("unknown pseudo");
|
||||
}
|
||||
if ( !mod_sizes ) fatal("Missing size specification");
|
||||
if ( databytes>maxadr ) error("Maximum data area size exceeded") ;
|
||||
}
|
||||
|
||||
setline() {
|
||||
|
||||
/* Get line numbers correct */
|
||||
|
||||
if ( pstate.s_fline &&
|
||||
ctrunc(pstate.s_fline->instr_num) == sp_fpseu ) {
|
||||
/* Already one present */
|
||||
pstate.s_fline->ad.ad_ln.ln_extra++ ;
|
||||
} else {
|
||||
newline(LINES) ;
|
||||
pstate.s_fline->instr_num= sp_fpseu ;
|
||||
pstate.s_fline->ad.ad_ln.ln_extra= 0 ;
|
||||
pstate.s_fline->ad.ad_ln.ln_first= line_num ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cons_t maxval(bits) int bits ; {
|
||||
/* find the maximum positive value,
|
||||
* fitting in 'bits' bits AND
|
||||
* fitting in a 'cons_t' .
|
||||
*/
|
||||
|
||||
cons_t val ;
|
||||
val=1 ;
|
||||
while ( bits-- ) {
|
||||
val<<= 1 ;
|
||||
if ( val<0 ) return ~val ;
|
||||
}
|
||||
return val-1 ;
|
||||
}
|
||||
|
||||
setsizes() {
|
||||
maxadr = maxval(8*ptrsize) ;
|
||||
maxint = maxval(8*wordsize-1) ;
|
||||
maxunsig = maxval(8*wordsize) ;
|
||||
maxdint = maxval(2*8*wordsize-1) ;
|
||||
maxdunsig = maxval(2*8*wordsize) ;
|
||||
}
|
||||
|
||||
exchange(p1,p2) {
|
||||
int size, line ;
|
||||
int l_of_p1, l_of_p2, l_of_before ;
|
||||
register line_t *t_lnp,*a_lnp, *b_lnp ;
|
||||
|
||||
/* Since the lines are linked backwards it is easy
|
||||
* to count the number of lines backwards.
|
||||
* Each instr counts for 1, each pseudo for ln_extra + 1.
|
||||
* The line numbers in error messages etc. are INCORRECT
|
||||
* If exc's are used.
|
||||
*/
|
||||
|
||||
line= line_num ; size=0 ;
|
||||
newline(LINES) ; a_lnp=pstate.s_fline ;
|
||||
a_lnp->instr_num= sp_fpseu ;
|
||||
a_lnp->ad.ad_ln.ln_first= line ;
|
||||
a_lnp->ad.ad_ln.ln_extra= -1 ;
|
||||
for ( ; a_lnp ; a_lnp= a_lnp->l_next ) {
|
||||
line-- ;
|
||||
switch ( ctrunc(a_lnp->instr_num) ) {
|
||||
case sp_fpseu :
|
||||
line= a_lnp->ad.ad_ln.ln_first ;
|
||||
size += a_lnp->ad.ad_ln.ln_extra ;
|
||||
break ;
|
||||
case sp_ilb1 :
|
||||
a_lnp->ad.ad_lp->l_min -= p2 ;
|
||||
break ;
|
||||
}
|
||||
size++ ;
|
||||
if ( size>=p1 ) break ;
|
||||
}
|
||||
if ( ( size-= p1 )>0 ) {
|
||||
if ( ctrunc(a_lnp->instr_num) !=sp_fpseu ) {
|
||||
fatal("EXC inconsistency") ;
|
||||
}
|
||||
doinsert(a_lnp,line,size-1) ;
|
||||
a_lnp->ad.ad_ln.ln_extra -= size ;
|
||||
size=0 ;
|
||||
} else {
|
||||
if( a_lnp) doinsert(a_lnp,line,-1) ;
|
||||
}
|
||||
b_lnp= a_lnp ;
|
||||
while ( b_lnp ) {
|
||||
b_lnp= b_lnp->l_next ;
|
||||
line-- ;
|
||||
switch ( ctrunc(b_lnp->instr_num) ) {
|
||||
case sp_fpseu :
|
||||
size += b_lnp->ad.ad_ln.ln_extra ;
|
||||
line = b_lnp->ad.ad_ln.ln_first ;
|
||||
break ;
|
||||
case sp_ilb1 :
|
||||
b_lnp->ad.ad_lp->l_min += p1 ;
|
||||
break ;
|
||||
}
|
||||
size++ ;
|
||||
if ( size>=p2 ) break ;
|
||||
}
|
||||
if ( !b_lnp ) { /* if a_lnp==0, so is b_lnp */
|
||||
fatal("Cannot perform exchange") ;
|
||||
}
|
||||
if ( ( size-= p2 )>0 ) {
|
||||
if ( ctrunc(b_lnp->instr_num) !=sp_fpseu ) {
|
||||
fatal("EXC inconsistency") ;
|
||||
}
|
||||
doinsert(b_lnp,line,size-1) ;
|
||||
b_lnp->ad.ad_ln.ln_extra -= size ;
|
||||
} else {
|
||||
doinsert(b_lnp,line,-1) ;
|
||||
}
|
||||
t_lnp = b_lnp->l_next ;
|
||||
b_lnp->l_next = pstate.s_fline ;
|
||||
pstate.s_fline= a_lnp->l_next ;
|
||||
a_lnp->l_next=t_lnp ;
|
||||
}
|
||||
|
||||
doinsert(lnp,first,extra) line_t *lnp ; {
|
||||
/* Beware : s_fline will be clobbered and restored */
|
||||
register line_t *t_lnp ;
|
||||
|
||||
t_lnp= pstate.s_fline;
|
||||
pstate.s_fline= lnp->l_next ;
|
||||
newline(LINES) ;
|
||||
pstate.s_fline->instr_num= sp_fpseu ;
|
||||
pstate.s_fline->ad.ad_ln.ln_first= first ;
|
||||
pstate.s_fline->ad.ad_ln.ln_extra= extra ;
|
||||
lnp->l_next= pstate.s_fline ;
|
||||
pstate.s_fline= t_lnp; /* restore */
|
||||
}
|
||||
|
||||
putval() {
|
||||
switch(valtype){
|
||||
case sp_cst2:
|
||||
extconst(argval);
|
||||
return ;
|
||||
case sp_ilb1:
|
||||
extloc(loclookup(tabval,OCCURRING));
|
||||
return ;
|
||||
case sp_dnam:
|
||||
extglob(glo2lookup(string,OCCURRING),(cons_t)0);
|
||||
return ;
|
||||
case sp_doff:
|
||||
extglob(glo2lookup(string,OCCURRING),argval);
|
||||
return ;
|
||||
case sp_pnam:
|
||||
extpro(prolookup(string,PRO_OCC));
|
||||
return ;
|
||||
case sp_scon:
|
||||
extstring() ;
|
||||
return ;
|
||||
case sp_fcon:
|
||||
extxcon(DATA_FCON) ;
|
||||
return ;
|
||||
case sp_icon:
|
||||
extvcon(DATA_ICON) ;
|
||||
return ;
|
||||
case sp_ucon:
|
||||
extvcon(DATA_UCON) ;
|
||||
return ;
|
||||
default:
|
||||
fatal("putval notreached") ;
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
|
||||
chkstart() {
|
||||
static int absout = 0 ;
|
||||
|
||||
if ( absout ) return ;
|
||||
if ( !oksizes ) fatal("missing size specification") ;
|
||||
setmode(DATA_CONST) ;
|
||||
extconst((cons_t)0) ;
|
||||
databytes= wordsize ;
|
||||
setmode(DATA_REP) ;
|
||||
if ( wordsize<ABSSIZE ) {
|
||||
register factor = ABSSIZE/wordsize - 1 ;
|
||||
extadr( (cons_t) factor ) ;
|
||||
databytes += factor * wordsize ;
|
||||
}
|
||||
absout++ ;
|
||||
memtype= HOLBSS ;
|
||||
}
|
||||
|
||||
typealign(new) enum m_type new ; {
|
||||
if ( memtype==new ) return ;
|
||||
align(wordsize);
|
||||
memtype=new ;
|
||||
}
|
||||
|
||||
sizealign(size) cons_t size ; {
|
||||
align( size>wordsize ? wordsize : (int)size ) ;
|
||||
}
|
||||
|
||||
align(size) int size ; {
|
||||
while ( databytes%size ) {
|
||||
setmode(DATA_BYTES) ;
|
||||
ext8(0) ;
|
||||
databytes++ ;
|
||||
}
|
||||
}
|
||||
|
||||
extconst(n) cons_t n ; {
|
||||
setmode(DATA_CONST);
|
||||
extword(n);
|
||||
}
|
||||
|
||||
extbss(n) cons_t n ; {
|
||||
cons_t objsize,amount ;
|
||||
cons_t sv_argval;
|
||||
int sv_tabval;
|
||||
|
||||
if ( n<=0 ) {
|
||||
if ( n<0 ) werror("negative bss/hol size") ;
|
||||
if ( table2()==sp_cend || table2()==sp_cend) {
|
||||
werror("Unexpected end-of-line") ;
|
||||
}
|
||||
return ;
|
||||
}
|
||||
setmode(DATA_NUL) ; /* flush descriptor */
|
||||
objsize= valsize();
|
||||
if ( objsize==0 ) {
|
||||
werror("Unexpected end-of-line");
|
||||
return;
|
||||
}
|
||||
if ( n%objsize != 0 ) error("BSS/HOL incompatible sizes");
|
||||
sv_tabval = tabval;
|
||||
sv_argval = argval;
|
||||
getarg(sp_cst2);
|
||||
if ( argval<0 || argval>1 ) error("illegal last argument") ;
|
||||
databytes +=n ;
|
||||
if (argval == 1) {
|
||||
tabval = sv_tabval;
|
||||
argval = sv_argval;
|
||||
putval();
|
||||
amount= n/objsize ;
|
||||
if ( amount>1 ) {
|
||||
setmode(DATA_REP);
|
||||
extadr(amount-1) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
n = (n + wordsize - 1) / wordsize;
|
||||
while (n > MAXBYTE) {
|
||||
setmode(DATA_BSS);
|
||||
ext8(MAXBYTE);
|
||||
n -= MAXBYTE;
|
||||
}
|
||||
setmode(DATA_BSS);
|
||||
ext8((int) n);
|
||||
}
|
||||
}
|
||||
|
||||
extloc(lbp) register locl_t *lbp; {
|
||||
|
||||
/*
|
||||
* assemble a pointer constant from a local label.
|
||||
* For example con *1
|
||||
*/
|
||||
setmode(DATA_IPTR);
|
||||
data_reloc( chp_cast lbp,dataoff,RELLOC);
|
||||
extadr((cons_t)0);
|
||||
}
|
||||
|
||||
extglob(agbp,off) glob_t *agbp; cons_t off; {
|
||||
register glob_t *gbp;
|
||||
|
||||
/*
|
||||
* generate a word of data that is defined by a global symbol.
|
||||
* Various relocation has to be prepared here in some cases
|
||||
*/
|
||||
gbp=agbp;
|
||||
setmode(DATA_DPTR);
|
||||
if ( gbp->g_status&DEF ) {
|
||||
extadr(gbp->g_val.g_addr+off);
|
||||
} else {
|
||||
data_reloc( chp_cast gbp,dataoff,RELGLO);
|
||||
extadr(off);
|
||||
}
|
||||
}
|
||||
|
||||
extpro(aprp) proc_t *aprp; {
|
||||
/*
|
||||
* generate a addres that is defined by a procedure descriptor.
|
||||
*/
|
||||
consiz= ptrsize ; setmode(DATA_UCON);
|
||||
extarb((int)ptrsize,(long)(aprp->p_num));
|
||||
}
|
||||
|
||||
extstring() {
|
||||
register char *s;
|
||||
register n ;
|
||||
|
||||
/*
|
||||
* generate data for a string.
|
||||
*/
|
||||
for(n=strlngth,s=string ; n--; ) {
|
||||
setmode(DATA_BYTES) ;
|
||||
ext8(*s++);
|
||||
}
|
||||
return ;
|
||||
}
|
||||
|
||||
extxcon(header) {
|
||||
register char *s ;
|
||||
register n;
|
||||
|
||||
/*
|
||||
* generate data for a floating constant initialized by a string.
|
||||
*/
|
||||
|
||||
setmode(header);
|
||||
s = string ;
|
||||
for (n=strlngth ; n-- ;) {
|
||||
if ( *s==0 ) error("Zero byte in initializer") ;
|
||||
ext8(*s++);
|
||||
}
|
||||
ext8(0);
|
||||
return ;
|
||||
}
|
||||
|
||||
extvcon(header) {
|
||||
extern long atol() ;
|
||||
/*
|
||||
* generate data for a constant initialized by a string.
|
||||
*/
|
||||
|
||||
setmode(header);
|
||||
if ( consiz>4 ) {
|
||||
error("Size of initializer exceeds loader capability") ;
|
||||
}
|
||||
extarb((int)consiz,atol(string)) ;
|
||||
return ;
|
||||
}
|
||||
132
util/ass/asscm.c
132
util/ass/asscm.c
@@ -1,132 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
/* Core management for the EM assembler.
|
||||
two routines:
|
||||
getarea(size)
|
||||
returns a pointer to a free area of 'size' bytes.
|
||||
freearea(ptr,size)
|
||||
free's the area of 'size' bytes pointed to by ptr
|
||||
|
||||
Free blocks are linked together and kept sorted.
|
||||
Adjacent free blocks are collapsed.
|
||||
Free blocks with a size smaller then the administration cannot
|
||||
exist.
|
||||
The algorithm is first fit.
|
||||
*/
|
||||
|
||||
#include "ass00.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
#ifdef MEMUSE
|
||||
static unsigned m_used = 0 ;
|
||||
static unsigned m_free = 0 ;
|
||||
#endif
|
||||
|
||||
struct freeblock {
|
||||
struct freeblock *f_next ;
|
||||
unsigned f_size ;
|
||||
} ;
|
||||
|
||||
static struct freeblock freexx[2] = {
|
||||
{ freexx, 0 },
|
||||
{ freexx+1, 0 }
|
||||
} ;
|
||||
|
||||
#define freehead freexx[1]
|
||||
|
||||
#define CHUNK 2048 /* Smallest chunk to be gotten from UNIX */
|
||||
|
||||
area_t getarea(size) unsigned size ; {
|
||||
register struct freeblock *c_ptr,*l_ptr ;
|
||||
register char *ptr ;
|
||||
unsigned rqsize ;
|
||||
char *malloc() ;
|
||||
|
||||
size = ((size + (sizeof(int) - 1)) / sizeof(int)) * sizeof(int);
|
||||
#ifdef MEMUSE
|
||||
m_used += size ;
|
||||
m_free -= size ;
|
||||
#endif
|
||||
for(;;) {
|
||||
for ( l_ptr= &freehead, c_ptr= freehead.f_next ;
|
||||
c_ptr!= &freehead ; c_ptr = c_ptr->f_next ) {
|
||||
if ( size==c_ptr->f_size ) {
|
||||
l_ptr->f_next= c_ptr->f_next ;
|
||||
return (area_t) c_ptr ;
|
||||
}
|
||||
if ( size+sizeof freehead <= c_ptr->f_size ) {
|
||||
c_ptr->f_size -= size ;
|
||||
return (area_t) ((char *) c_ptr + c_ptr->f_size) ;
|
||||
}
|
||||
l_ptr = c_ptr ;
|
||||
}
|
||||
rqsize = size<CHUNK ? CHUNK : size ;
|
||||
for(;;){
|
||||
ptr = malloc( rqsize ) ;
|
||||
if ( ptr ) break ; /* request succesfull */
|
||||
rqsize /= 2 ;
|
||||
rqsize -= rqsize%sizeof (int) ;
|
||||
if ( rqsize < sizeof freehead ) {
|
||||
fatal("Out of memory") ;
|
||||
}
|
||||
}
|
||||
freearea((area_t)ptr,rqsize) ;
|
||||
#ifdef MEMUSE
|
||||
m_used += rqsize ;
|
||||
#endif
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
freearea(ptr,size) register area_t ptr ; unsigned size ; {
|
||||
register struct freeblock *c_ptr, *l_ptr ;
|
||||
|
||||
size = ((size + (sizeof(int) - 1)) / sizeof(int)) * sizeof(int);
|
||||
#ifdef MEMUSE
|
||||
m_free += size ;
|
||||
m_used -= size ;
|
||||
#endif
|
||||
for ( l_ptr= &freehead, c_ptr=freehead.f_next ;
|
||||
c_ptr!= &freehead ; c_ptr= c_ptr->f_next ) {
|
||||
if ( (area_t)c_ptr>ptr ) break ;
|
||||
l_ptr= c_ptr ;
|
||||
}
|
||||
/* now insert between l_ptr and c_ptr */
|
||||
/* Beware they may both point to freehead */
|
||||
|
||||
#ifdef MEMUSE
|
||||
if ( ((char *)l_ptr)+l_ptr->f_size> (char *)ptr && (char *)l_ptr<=(char *)ptr )
|
||||
fatal("Double freed") ;
|
||||
if ( ((char *)ptr)+size > (char *)c_ptr && (char *)ptr<=(char *)c_ptr )
|
||||
fatal("Frreed double") ;
|
||||
#endif
|
||||
/* Is the block before this one adjacent ? */
|
||||
if ( ((char *)l_ptr) + l_ptr->f_size == (char *) ptr ) {
|
||||
l_ptr->f_size += size ; /* yes */
|
||||
} else {
|
||||
/* No, create an entry */
|
||||
((struct freeblock *)ptr)->f_next = c_ptr ;
|
||||
((struct freeblock *)ptr)->f_size = size ;
|
||||
l_ptr->f_next = (struct freeblock *)ptr ;
|
||||
l_ptr = (struct freeblock *)ptr ;
|
||||
}
|
||||
/* Are the two entries adjacent ? */
|
||||
if ( (char *)l_ptr + l_ptr->f_size == (char *) c_ptr ) {
|
||||
/* the two entries are adjacent */
|
||||
l_ptr->f_next = c_ptr->f_next ;
|
||||
l_ptr->f_size += c_ptr->f_size ;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MEMUSE
|
||||
memuse() {
|
||||
printf("Free %7u, Used %7u, Total %7u\n",m_free,m_used,m_free+m_used);
|
||||
}
|
||||
#endif
|
||||
138
util/ass/assda.c
138
util/ass/assda.c
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
#include "ass00.h"
|
||||
#include "assex.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
static char rcs_ass[]= RCS_ASS ;
|
||||
static char rcs_ex[] = RCS_EX ;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* global data
|
||||
*/
|
||||
|
||||
int wordsize ;
|
||||
int ptrsize ;
|
||||
cons_t maxadr ;
|
||||
cons_t maxint;
|
||||
cons_t maxdint;
|
||||
cons_t maxunsig;
|
||||
cons_t maxdunsig;
|
||||
|
||||
/*
|
||||
The structure containing used for procedure environment stacking
|
||||
*/
|
||||
stat_t pstate ;
|
||||
|
||||
/*
|
||||
* pointers to not yet allocated storage
|
||||
*/
|
||||
glob_t *mglobs; /* pointer to module symbols */
|
||||
glob_t *xglobs; /* pointer to extern symbols */
|
||||
proc_t *mprocs; /* pointer to local procs */
|
||||
proc_t *xprocs; /* pointer to external procs */
|
||||
ptab_t *proctab; /* pointer to proctab[] */
|
||||
|
||||
/*
|
||||
* some array and structures of known size
|
||||
*/
|
||||
FILE *ifile; /* input file buffer */
|
||||
FILE *tfile; /* code file buffer */
|
||||
FILE *dfile; /* data file buffer */
|
||||
FILE *rtfile; /* code file buffer */
|
||||
FILE *rdfile; /* data file buffer */
|
||||
char string[MAXSTRING];
|
||||
|
||||
/*
|
||||
* some other pointers
|
||||
*/
|
||||
glob_t *lastglosym; /* last global symbol */
|
||||
glob_t *curglosym; /* current global symbol */
|
||||
relc_t *f_data = (relc_t *)0 ; /* first data reloc pointer */
|
||||
relc_t *l_data = (relc_t *)0 ; /* last data reloc pointer */
|
||||
relc_t *f_text = (relc_t *)0 ; /* first text reloc pointer */
|
||||
relc_t *l_text = (relc_t *)0 ; /* last text reloc pointer */
|
||||
|
||||
/*
|
||||
* some indices
|
||||
*/
|
||||
int strlngth; /* index in string[] */
|
||||
FOFFSET inpoff; /* offset in current input file */
|
||||
FOFFSET libeof; /* ceiling for above number */
|
||||
|
||||
/*
|
||||
* some other counters
|
||||
*/
|
||||
int procnum; /* generic for unique proc-descr. */
|
||||
cons_t prog_size; /* length of current proc */
|
||||
int max_bytes;
|
||||
int pass;
|
||||
int line_num; /* line number for error messages */
|
||||
int nerrors; /* number of nonfatal errors */
|
||||
cons_t consiz; /* size of U,I or F value */
|
||||
cons_t textbytes; /* size of code file */
|
||||
cons_t databytes; /* highwater mark in data */
|
||||
FOFFSET dataoff; /* size of data file */
|
||||
FOFFSET textoff; /* size of text file */
|
||||
FOFFSET lastoff; /* previous size before last block */
|
||||
int datamode; /* what kind of data */
|
||||
int datablocks; /* number of datablocks written out */
|
||||
relc_t *lastheader; /* pointer into datareloc */
|
||||
cons_t holbase;
|
||||
cons_t holsize;
|
||||
int unresolved; /* # of unresolved references */
|
||||
int sourcelines; /* number of lines in source program*/
|
||||
int intflags = 1; /* flags for interpreter */
|
||||
/*
|
||||
* some flags
|
||||
*/
|
||||
int archmode; /* reading library ? */
|
||||
int procflag; /* print "namelist" of procedures */
|
||||
#ifdef DUMP
|
||||
int c_flag; /* print unused opcodes */
|
||||
char opcnt1[256]; /* count primary opcodes */
|
||||
char opcnt2[256]; /* count secondary opcodes */
|
||||
char opcnt3[256]; /* count long opcodes */
|
||||
#endif
|
||||
int d_flag = 0; /* don't dump */
|
||||
int r_flag = 0; /* don't dump relocation tables */
|
||||
#ifdef JOHAN
|
||||
int jflag;
|
||||
#endif
|
||||
int wflag = 0; /* don't issue warning messages */
|
||||
int Uflag = 0; /* exit status 0 on unresolved refs */
|
||||
int eof_seen;
|
||||
int mod_sizes; /* Size info in current module ok? */
|
||||
|
||||
#define BASE (sizeof (struct lines) - sizeof (addr_u))
|
||||
|
||||
char linesize[VALLOW+1] = {
|
||||
BASE, /* MISSING */
|
||||
BASE + sizeof (cons_t), /* CONST */
|
||||
BASE + sizeof prp_cast, /* PROCNAME */
|
||||
BASE + sizeof gbp_cast, /* GLOSYM */
|
||||
BASE + sizeof lbp_cast, /* LOCSYM */
|
||||
BASE + sizeof (struct sad_df), /* GLOOFF */
|
||||
BASE + sizeof (struct sad_ln), /* LINES */
|
||||
BASE /* VALLOW */
|
||||
} ;
|
||||
|
||||
/*
|
||||
* miscellaneous
|
||||
*/
|
||||
char *progname; /* argv[0] */
|
||||
char *curfile = 0; /* name of current file */
|
||||
char *eout = "e.out";
|
||||
arch_t archhdr;
|
||||
siz_t sizes[NDEFAULT] = {
|
||||
/* mlab, glab,mproc,xproc, proc */
|
||||
{ 151, 29, 31, 73, 130 }, /* small */
|
||||
{ 307, 127, 151, 401, 460 }, /* medium */
|
||||
{ 601, 251, 151, 401, 600 }, /* large */
|
||||
{1601, 1601, 1601, 1601, 2000 } /* extra large */
|
||||
};
|
||||
siz_t *oursize = &sizes[2] ; /* point to selected sizes */
|
||||
165
util/ass/assex.h
165
util/ass/assex.h
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/*
|
||||
* global data
|
||||
*/
|
||||
|
||||
#define RCS_EX "$Id$"
|
||||
|
||||
extern int wordsize;
|
||||
extern int ptrsize;
|
||||
extern cons_t maxadr;
|
||||
extern cons_t maxint;
|
||||
extern cons_t maxdint;
|
||||
extern cons_t maxunsig;
|
||||
extern cons_t maxdunsig;
|
||||
|
||||
/*
|
||||
* tables loaded from em_libraries
|
||||
*/
|
||||
extern char em_flag[];
|
||||
|
||||
/*
|
||||
The structure containing used for procedure environment stacking
|
||||
*/
|
||||
extern stat_t pstate ;
|
||||
|
||||
/*
|
||||
* pointers to not yet allocated storage
|
||||
*/
|
||||
extern glob_t *mglobs;
|
||||
extern glob_t *xglobs;
|
||||
extern proc_t *mprocs;
|
||||
extern proc_t *xprocs;
|
||||
extern ptab_t *proctab;
|
||||
|
||||
extern FILE *ifile;
|
||||
extern FILE *tfile;
|
||||
extern FILE *dfile;
|
||||
extern FILE *rtfile;
|
||||
extern FILE *rdfile;
|
||||
extern char string[];
|
||||
|
||||
/*
|
||||
* some other pointers
|
||||
*/
|
||||
extern glob_t *lastglosym;
|
||||
extern glob_t *curglosym;
|
||||
extern siz_t *oursize;
|
||||
extern relc_t *f_data;
|
||||
extern relc_t *l_data;
|
||||
extern relc_t *f_text;
|
||||
extern relc_t *l_text;
|
||||
|
||||
/*
|
||||
* some indices
|
||||
*/
|
||||
extern int strlngth;
|
||||
extern FOFFSET inpoff;
|
||||
extern FOFFSET libeof;
|
||||
|
||||
/*
|
||||
* some other counters
|
||||
*/
|
||||
extern int procnum;
|
||||
extern cons_t prog_size;
|
||||
extern int max_bytes;
|
||||
extern int pass;
|
||||
extern int line_num;
|
||||
extern int nerrors;
|
||||
extern cons_t textbytes;
|
||||
extern cons_t databytes;
|
||||
extern FOFFSET dataoff;
|
||||
extern FOFFSET textoff;
|
||||
extern FOFFSET lastoff;
|
||||
extern int datamode;
|
||||
extern int datablocks;
|
||||
extern relc_t *lastheader;
|
||||
extern cons_t holbase;
|
||||
extern cons_t holsize;
|
||||
extern int unresolved;
|
||||
extern int sourcelines;
|
||||
extern int intflags;
|
||||
/*
|
||||
* some flags
|
||||
*/
|
||||
extern int archmode;
|
||||
extern int procflag;
|
||||
#ifdef DUMP
|
||||
extern int c_flag;
|
||||
extern char opcnt1[];
|
||||
extern char opcnt2[];
|
||||
extern char opcnt3[];
|
||||
#endif
|
||||
extern int d_flag;
|
||||
extern int r_flag;
|
||||
#ifdef JOHAN
|
||||
extern int jflag;
|
||||
#endif
|
||||
extern int wflag;
|
||||
extern int Uflag;
|
||||
extern int eof_seen;
|
||||
extern int mod_sizes;
|
||||
/*
|
||||
* miscellaneous
|
||||
*/
|
||||
extern cons_t consiz;
|
||||
extern char *progname;
|
||||
extern char *curfile;
|
||||
extern char *eout;
|
||||
extern arch_t archhdr;
|
||||
extern siz_t sizes[];
|
||||
|
||||
extern char linesize[];
|
||||
|
||||
/*
|
||||
* from asstb.c
|
||||
*/
|
||||
|
||||
extern char *opindex[] ;
|
||||
extern char opchoice[] ;
|
||||
extern int maxinsl ;
|
||||
|
||||
/*
|
||||
* types of value returning routines
|
||||
*/
|
||||
#ifndef CPM
|
||||
extern int tmpfil();
|
||||
extern FILE *frewind();
|
||||
#endif
|
||||
extern int xgetc();
|
||||
extern unsigned get8();
|
||||
extern int get16();
|
||||
extern cons_t get32();
|
||||
extern cons_t xgeta();
|
||||
extern cons_t parval();
|
||||
extern cons_t valsize();
|
||||
extern cons_t xgetarb();
|
||||
extern char *findnop();
|
||||
extern char *findfit();
|
||||
extern glob_t *glolookup();
|
||||
extern glob_t *glo2lookup();
|
||||
extern glob_t *xglolookup();
|
||||
extern locl_t *loclookup();
|
||||
extern proc_t *prolookup();
|
||||
extern proc_t *enterproc();
|
||||
extern proc_t *searchproc();
|
||||
extern relc_t *text_reloc();
|
||||
extern relc_t *data_reloc();
|
||||
extern area_t getarea();
|
||||
|
||||
/*
|
||||
* all used library routines
|
||||
*/
|
||||
extern char *malloc();
|
||||
extern int open();
|
||||
extern int creat();
|
||||
extern int getpid();
|
||||
extern int unlink();
|
||||
extern int close();
|
||||
extern int strcmp();
|
||||
extern char *strcpy();
|
||||
|
||||
#define void int
|
||||
291
util/ass/assrl.c
291
util/ass/assrl.c
@@ -1,291 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ass00.h"
|
||||
#include "assex.h"
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
#define COPYFINAL 1
|
||||
#define COPYTEMP 0
|
||||
|
||||
/*
|
||||
* collection of routines to deal with relocation business
|
||||
*/
|
||||
|
||||
void dataprocess();
|
||||
void textprocess();
|
||||
relc_t *
|
||||
text_reloc(glosym,off,typ) glob_t *glosym; FOFFSET off ; int typ ; {
|
||||
|
||||
/*
|
||||
* prepare the relocation that has to be done at text-offset off
|
||||
* according to global symbol glosym.
|
||||
* NOTE: The pointer glosym will point into mglobs[], while at
|
||||
* the time copyout() is called all the symbols here
|
||||
* will have disappeared.
|
||||
* The procedure upd_reloc() will change this pointer
|
||||
* into the one in xglobs[] later.
|
||||
*/
|
||||
|
||||
register relc_t *nxtextreloc ;
|
||||
|
||||
nxtextreloc= rlp_cast getarea(sizeof *nxtextreloc) ;
|
||||
if ( !f_text ) {
|
||||
f_text= nxtextreloc ;
|
||||
} else {
|
||||
l_text->r_next= nxtextreloc ;
|
||||
}
|
||||
nxtextreloc->r_next= rlp_cast 0 ;
|
||||
l_text= nxtextreloc ;
|
||||
nxtextreloc->r_off = off;
|
||||
nxtextreloc->r_val.rel_gp = glosym;
|
||||
nxtextreloc->r_typ = typ; /* flags of instruction */
|
||||
return(nxtextreloc);
|
||||
}
|
||||
|
||||
relc_t *
|
||||
data_reloc(arg,off,typ) char *arg ; FOFFSET off ; int typ ; {
|
||||
|
||||
/*
|
||||
* Same as above.
|
||||
*/
|
||||
|
||||
register relc_t *nxdatareloc ;
|
||||
|
||||
nxdatareloc= rlp_cast getarea(sizeof *nxdatareloc) ;
|
||||
if ( !f_data ) {
|
||||
f_data= nxdatareloc ;
|
||||
} else {
|
||||
l_data->r_next= nxdatareloc ;
|
||||
}
|
||||
nxdatareloc->r_next= rlp_cast 0 ;
|
||||
l_data= nxdatareloc ;
|
||||
nxdatareloc->r_off = off;
|
||||
nxdatareloc->r_val.rel_lp = lbp_cast arg;
|
||||
nxdatareloc->r_typ = typ;
|
||||
return(nxdatareloc);
|
||||
}
|
||||
|
||||
copyout() {
|
||||
register i;
|
||||
int remtext ;
|
||||
|
||||
/*
|
||||
* Make the e.out file that looks as follows:
|
||||
*
|
||||
* __________________________
|
||||
* | MAGIC | \
|
||||
* | FLAGS | \
|
||||
* | UNRESOLVED | \
|
||||
* | VERSION | | 8*(2-byte word) header
|
||||
* | WORDSIZE | | for interpreter selection
|
||||
* | PTRSIZE | /
|
||||
* | <UNUSED> | /
|
||||
* | <UNUSED> | /
|
||||
* | NTEXT | \
|
||||
* | NDATA | \
|
||||
* | NPROC | \
|
||||
* | ENTRY-POINT | | 8*(wordsize-word) header
|
||||
* | NLINES | | for interpreter proper
|
||||
* | <UNUSED> | /
|
||||
* | <UNUSED> | /
|
||||
* | <UNUSED> | /
|
||||
* |________________________|
|
||||
* | |
|
||||
* | TEXT | zero filled
|
||||
* | | if not word multiple
|
||||
* |________________________|
|
||||
* | |
|
||||
* | DATA |
|
||||
* | |
|
||||
* |________________________|
|
||||
* | |
|
||||
* | PROCTABLE |
|
||||
* | |
|
||||
* |________________________|
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
remtext = textbytes%wordsize ;
|
||||
if ( remtext != 0 ) remtext = wordsize-remtext ;
|
||||
|
||||
if ((ifile = fopen(eout,"w")) == 0 )
|
||||
fatal("can't create e.out");
|
||||
#ifdef CPM
|
||||
fclose(tfile); tfile=fopen("TFILE.$$$", "r");
|
||||
fclose(dfile); dfile=fopen("DFILE.$$$", "r");
|
||||
#else
|
||||
tfile=frewind(tfile);
|
||||
dfile=frewind(dfile);
|
||||
#endif
|
||||
xput16(as_magic,ifile);
|
||||
xput16(intflags,ifile);
|
||||
xput16(unresolved,ifile);
|
||||
xput16(VERSION,ifile);
|
||||
xput16(wordsize,ifile);
|
||||
xput16(ptrsize,ifile);
|
||||
xput16(0,ifile);
|
||||
xput16(0,ifile);
|
||||
xputa(textbytes+remtext ,ifile);
|
||||
xputa((cons_t)datablocks,ifile);
|
||||
xputa((cons_t)procnum,ifile);
|
||||
xputa((cons_t)searchproc(MAIN,xprocs,oursize->n_xproc)->p_num,
|
||||
ifile);
|
||||
xputa((cons_t)sourcelines,ifile);
|
||||
xputa((cons_t)databytes,ifile);
|
||||
xputa((cons_t)0,ifile);
|
||||
xputa((cons_t)0,ifile);
|
||||
|
||||
textprocess(tfile,ifile);
|
||||
while ( remtext-- ) xputc(0,ifile) ;
|
||||
|
||||
dataprocess(dfile,ifile);
|
||||
for (i=0;i<procnum;i++) {
|
||||
xputarb(ptrsize,proctab[i].pr_loc,ifile);
|
||||
xputarb(ptrsize,proctab[i].pr_off,ifile);
|
||||
}
|
||||
if ( fclose(ifile)==EOF ) ;
|
||||
}
|
||||
|
||||
dataprocess(f1,f2) FILE *f1,*f2; {
|
||||
relc_t datareloc;
|
||||
FOFFSET i;
|
||||
register ieof ;
|
||||
|
||||
#ifdef CPM
|
||||
fclose(rdfile); rdfile=fopen("RDFILE.$$$", "r");
|
||||
#else
|
||||
rdfile=frewind(rdfile) ;
|
||||
#endif
|
||||
ieof=getblk(rdfile,(char *)(&datareloc.r_off),
|
||||
sizeof datareloc - sizeof datareloc.r_next) ;
|
||||
for (i=0 ; i<dataoff && !ieof ; i++) {
|
||||
if (i==datareloc.r_off) {
|
||||
switch(datareloc.r_typ) {
|
||||
case RELADR:
|
||||
xputa(xgeta(f1)+datareloc.r_val.rel_i,f2) ;
|
||||
i += ptrsize-1 ;
|
||||
break ;
|
||||
case RELGLO:
|
||||
if (datareloc.r_val.rel_gp->g_status&DEF) {
|
||||
xputa(xgeta(f1)+
|
||||
datareloc.r_val.rel_gp->g_val.g_addr,
|
||||
f2);
|
||||
i+= ptrsize-1 ;
|
||||
break ;
|
||||
}
|
||||
if ( unresolved == 0 )
|
||||
fatal("Definition botch") ;
|
||||
case RELHEAD:
|
||||
xputc((int)(xgetc(f1)+datareloc.r_val.rel_i),
|
||||
f2);
|
||||
break;
|
||||
default:
|
||||
fatal("Bad r_typ in dataprocess");
|
||||
}
|
||||
ieof=getblk(rdfile,(char *)(&datareloc.r_off),
|
||||
sizeof datareloc - sizeof datareloc.r_next) ;
|
||||
} else
|
||||
xputc(xgetc(f1),f2);
|
||||
}
|
||||
for ( ; i<dataoff ; i++ ) xputc(xgetc(f1),f2) ;
|
||||
if ( !ieof && !getblk(rdfile,(char *)&datareloc,1) )
|
||||
fatal("data relocation botch") ;
|
||||
}
|
||||
|
||||
textprocess(f1,f2) FILE *f1,*f2; {
|
||||
relc_t textreloc;
|
||||
cons_t n;
|
||||
FOFFSET i;
|
||||
FILE *otfile ;
|
||||
int insl ; register int ieof ;
|
||||
char *op_curr ;
|
||||
register FOFFSET keep ;
|
||||
|
||||
#ifdef CPM
|
||||
fclose(rtfile); rtfile=fopen("RTFILE.$$$", "r");
|
||||
#else
|
||||
rtfile=frewind(rtfile) ;
|
||||
#endif
|
||||
keep = textoff ; textoff=0 ; otfile=tfile ; tfile=f2 ;
|
||||
/* This redirects the output of genop */
|
||||
ieof=getblk(rtfile,(char *)(&textreloc.r_off),
|
||||
sizeof textreloc - sizeof textreloc.r_next) ;
|
||||
for(i=0;i<keep && !ieof ;i++) {
|
||||
if( i == textreloc.r_off ) {
|
||||
if (textreloc.r_typ&RELMNS) {
|
||||
n=textreloc.r_val.rel_i;
|
||||
} else {
|
||||
if (textreloc.r_val.rel_gp->g_status&DEF) {
|
||||
n=textreloc.r_val.rel_gp->g_val.g_addr;
|
||||
} else {
|
||||
if ( unresolved==0 )
|
||||
fatal("Definition botch") ;
|
||||
xputc(xgetc(f1),f2) ;
|
||||
ieof=getblk(rtfile,(char *)(&textreloc.r_off),
|
||||
sizeof textreloc-sizeof textreloc.r_next);
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
op_curr = &opchoice[textreloc.r_typ& ~RELMNS] ;
|
||||
insl = oplength(*op_curr) ;
|
||||
genop(op_curr, n+xgetarb(insl,f1), PAR_G);
|
||||
i += insl-1 ;
|
||||
ieof=getblk(rtfile,(char *)(&textreloc.r_off),
|
||||
sizeof textreloc - sizeof textreloc.r_next) ;
|
||||
} else {
|
||||
xputc(xgetc(f1),f2) ;
|
||||
}
|
||||
}
|
||||
for ( ; i<keep ; i++ ) xputc(xgetc(f1),f2) ;
|
||||
if ( !ieof && !getblk(rtfile,(char *)&textreloc,1) )
|
||||
fatal("text relocation botch") ;
|
||||
textoff = keep ;
|
||||
tfile = otfile ;
|
||||
}
|
||||
|
||||
upd_reloc() {
|
||||
register relc_t *p;
|
||||
register glob_t *gbp;
|
||||
|
||||
/*
|
||||
* Change reloc-tables such that for every pointer into mglobs
|
||||
* either the corresponding pointer into xglobs or its value
|
||||
* is substituted.
|
||||
*
|
||||
* Use is made of the known order of mglobs and xglobs
|
||||
* see also getcore()
|
||||
*/
|
||||
|
||||
while ( p= f_text ) {
|
||||
gbp= p->r_val.rel_gp ;
|
||||
if( gbp->g_status&DEF ) {
|
||||
p->r_typ |= RELMNS;
|
||||
p->r_val.rel_i = gbp->g_val.g_addr;
|
||||
} else
|
||||
p->r_val.rel_gp = gbp->g_val.g_gp;
|
||||
putblk(rtfile,(char *)(&(p->r_off)),sizeof *p - sizeof p) ;
|
||||
f_text= p->r_next ; freearea( (area_t) p , sizeof *p ) ;
|
||||
}
|
||||
|
||||
while( p= f_data ) {
|
||||
if (p->r_typ == RELGLO) {
|
||||
gbp= p->r_val.rel_gp ;
|
||||
if(gbp->g_status&DEF) {
|
||||
p->r_typ = RELADR;
|
||||
p->r_val.rel_i = gbp->g_val.g_addr;
|
||||
} else
|
||||
p->r_val.rel_gp = gbp->g_val.g_gp;
|
||||
}
|
||||
putblk(rdfile,(char *)(&(p->r_off)),sizeof *p - sizeof p) ;
|
||||
f_data= p->r_next ; freearea( (area_t) p , sizeof *p ) ;
|
||||
}
|
||||
l_data= rlp_cast 0 ;
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
.\" $Id$
|
||||
.TH EM_ASS 6 "$Revision$"
|
||||
.ad
|
||||
.SH NAME
|
||||
em_ass \- EM assembler/loader
|
||||
.SH SYNOPSIS
|
||||
.B ~em/lib.bin/em_ass
|
||||
[options] argument ...
|
||||
.SH DESCRIPTION
|
||||
Em_ass assembles and links EM modules.
|
||||
Arguments may be flags, EM modules or libraries.
|
||||
Flags recognized are:
|
||||
.IP "-ss, -sm, -sl, -sx"
|
||||
Indicate that the program is small, medium, large, or extra large.
|
||||
Large is the default.
|
||||
.IP -p
|
||||
List all procedure names together with base-address (decimal and octal),
|
||||
procedure number and module of definition.
|
||||
.IP -d
|
||||
Used for debugging em_ass itself.
|
||||
.IP -U
|
||||
With this flag, em_ass has exit status 0 even when there are unresolved
|
||||
references.
|
||||
.PD
|
||||
.PP
|
||||
em_ass assembles and links together compact EM assembly language modules
|
||||
from files and libraries,
|
||||
producing an e.out file as described in [1].
|
||||
.PP
|
||||
Two different types of arguments are allowed:
|
||||
.IP "1 -"
|
||||
Compact EM assembly language modules (optimized or not), recognized by a
|
||||
magic number in the first word.
|
||||
.PD 0
|
||||
.IP "2 -"
|
||||
UNIX archives, as maintained by arch(1). These archives must contain
|
||||
EM modules only.
|
||||
.PD
|
||||
.PP
|
||||
EM modules may contain a library message specifying the names
|
||||
of procedures and external data defined inside the module.
|
||||
These will only be loaded
|
||||
if they contain definitions of procedures or data imported by
|
||||
previously assembled modules.
|
||||
When \fIack\fP(1) is provided with the -LIB flag it tells the
|
||||
EM-optimizer \fIem_opt\fP(6) to insert a library messages
|
||||
when optimizing modules.
|
||||
The EM-archiver \fIarch\fP(1) can be used to create libraries
|
||||
from EM modules.
|
||||
.PP
|
||||
Note that it is not possible to do a partial load;
|
||||
loading starts from compact EM code and produces binary
|
||||
EM code. No symbol table and no relocation bits are produced.
|
||||
.SH "SEE ALSO"
|
||||
ack(1), arch(1)
|
||||
.PD 0
|
||||
.IP [1]
|
||||
A.S. Tanenbaum, Hans van Staveren, Ed Keizer and Johan
|
||||
Stevenson "Description of a machine architecture for use with
|
||||
block structured languages" Informatica report IR-81.
|
||||
.SH DIAGNOSTICS
|
||||
Various diagnostics may be produced. In the case of compiler
|
||||
produced code the only messages to expect are "Out of memory"
|
||||
or of the
|
||||
form: Overflow in XXXX. The latter can usually be cured by giving
|
||||
a -sx flag,
|
||||
the former means the program is too big, dimishing
|
||||
the size of very large procedures can sometimes help.
|
||||
The most likely errors, however, are unresolved references,
|
||||
probably caused by the omission of a library argument.
|
||||
.SH AUTHOR
|
||||
Ed Keizer, Vrije Universiteit
|
||||
@@ -1,40 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*/
|
||||
/* Contents of flags used when describing interpreter opcodes */
|
||||
|
||||
#define RCS_IP "$Header$"
|
||||
|
||||
#define OPTYPE 07 /* type field in flag */
|
||||
|
||||
#define OPMINI 0 /* m MINI */
|
||||
#define OPSHORT 1 /* s SHORT */
|
||||
#define OPNO 2 /* - No operand */
|
||||
#define OP8 3 /* 1 1-byte signed operand */
|
||||
#define OP16 4 /* 2 2-byte signed operand */
|
||||
#define OP32 5 /* 4 4-byte signed operand */
|
||||
#define OP64 6 /* 8 8-byte signed operand */
|
||||
#define OP16U 7 /* u 2-byte unsigned operand */
|
||||
|
||||
#define OPESC 010 /* e escaped opcode */
|
||||
#define OPWORD 020 /* w operand is word multiple */
|
||||
#define OPNZ 040 /* o operand starts at 1 ( or wordsize if w-flag) */
|
||||
|
||||
#define OPRANGE 0300 /* Range of operands: Positive, negative, both */
|
||||
|
||||
#define OP_BOTH 0000 /* the default */
|
||||
#define OP_POS 0100 /* p Positive (>=0) operands only */
|
||||
#define OP_NEG 0200 /* n Negative (<0) operands only */
|
||||
|
||||
struct opform {
|
||||
char i_opcode ; /* the opcode number */
|
||||
char i_flag ; /* the flag byte */
|
||||
char i_low ; /* the interpreter first opcode */
|
||||
char i_num ; /* the number of shorts/minis (optional) */
|
||||
};
|
||||
|
||||
/* Escape indicators */
|
||||
|
||||
#define ESC 254 /* To escape group */
|
||||
#define ESC_L 255 /* To 32 and 64 bit operands */
|
||||
@@ -1,476 +0,0 @@
|
||||
/*
|
||||
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ip_spec.h"
|
||||
#include <stdio.h>
|
||||
#include <em_spec.h>
|
||||
#include <em_flag.h>
|
||||
|
||||
#ifndef NORCSID
|
||||
static char rcs_id[] = "$Id$" ;
|
||||
#endif
|
||||
|
||||
/* This program reads the human readable interpreter specification
|
||||
and produces a efficient machine representation that can be
|
||||
translated by a C-compiler.
|
||||
*/
|
||||
|
||||
#define NOTAB 600 /* The max no of interpreter specs */
|
||||
#define ESCAP 256
|
||||
|
||||
struct opform intable[NOTAB] ;
|
||||
struct opform *lastform = intable-1 ;
|
||||
|
||||
int nerror = 0 ;
|
||||
int atend = 0 ;
|
||||
int line = 1 ;
|
||||
int maxinsl= 0 ;
|
||||
|
||||
extern char em_mnem[][4] ;
|
||||
char esca[] = "escape" ;
|
||||
#define ename(no) ((no)==ESCAP?esca:em_mnem[(no)])
|
||||
|
||||
extern char em_flag[] ;
|
||||
|
||||
main(argc,argv) char **argv ; {
|
||||
if ( argc>1 ) {
|
||||
if ( freopen(argv[1],"r",stdin)==NULL) {
|
||||
fatal("Cannot open %s",argv[1]) ;
|
||||
}
|
||||
}
|
||||
if ( argc>2 ) {
|
||||
if ( freopen(argv[2],"w",stdout)==NULL) {
|
||||
fatal("Cannot create %s",argv[2]) ;
|
||||
}
|
||||
}
|
||||
if ( argc>3 ) {
|
||||
fatal("%s [ file [ file ] ]",argv[0]) ;
|
||||
}
|
||||
atend=0 ;
|
||||
readin();
|
||||
atend=1 ;
|
||||
checkall();
|
||||
if ( nerror==0 ) {
|
||||
writeout();
|
||||
}
|
||||
exit(nerror);
|
||||
}
|
||||
|
||||
readin() {
|
||||
register struct opform *nextform ;
|
||||
char *ident();
|
||||
char *firstid ;
|
||||
register maxl ;
|
||||
|
||||
maxl = 0 ;
|
||||
for ( nextform=intable ;
|
||||
!feof(stdin) && nextform<&intable[NOTAB] ; ) {
|
||||
firstid=ident() ;
|
||||
if ( *firstid=='\n' || feof(stdin) ) continue ;
|
||||
lastform=nextform ;
|
||||
nextform->i_opcode = getmnem(firstid) ;
|
||||
nextform->i_flag = decflag(ident()) ;
|
||||
switch ( nextform->i_flag&OPTYPE ) {
|
||||
case OPMINI:
|
||||
case OPSHORT:
|
||||
nextform->i_num = atoi(ident()) ;
|
||||
break ;
|
||||
}
|
||||
nextform->i_low = atoi(ident()) ;
|
||||
if ( *ident()!='\n' ) {
|
||||
int c ;
|
||||
error("End of line expected");
|
||||
while ( (c=readchar())!='\n' && c!=EOF ) ;
|
||||
}
|
||||
if ( oplength(nextform)>maxl ) maxl=oplength(nextform) ;
|
||||
nextform++ ;
|
||||
}
|
||||
if ( !feof(stdin) ) fatal("Internal table too small") ;
|
||||
maxinsl = maxl ;
|
||||
}
|
||||
|
||||
char *ident() {
|
||||
/* skip spaces and tabs, anything up to space,tab or eof is
|
||||
a identifier.
|
||||
Anything from # to end-of-line is an end-of-line.
|
||||
End-of-line is an identifier all by itself.
|
||||
*/
|
||||
|
||||
static char array[200] ;
|
||||
register int c ;
|
||||
register char *cc ;
|
||||
|
||||
do {
|
||||
c=readchar() ;
|
||||
} while ( c==' ' || c=='\t' ) ;
|
||||
for ( cc=array ; cc<&array[(sizeof array) - 1] ; cc++ ) {
|
||||
if ( c=='#' ) {
|
||||
do {
|
||||
c=readchar();
|
||||
} while ( c!='\n' && c!=EOF ) ;
|
||||
}
|
||||
*cc = c ;
|
||||
if ( c=='\n' && cc==array ) break ;
|
||||
c=readchar() ;
|
||||
if ( c=='\n' ) {
|
||||
pushback(c) ;
|
||||
break ;
|
||||
}
|
||||
if ( c==' ' || c=='\t' || c==EOF ) break ;
|
||||
}
|
||||
*++cc=0 ;
|
||||
return array ;
|
||||
}
|
||||
|
||||
int getmnem(str) char *str ; {
|
||||
char (*ptr)[4] ;
|
||||
|
||||
for ( ptr = em_mnem ; *ptr<= &em_mnem[sp_lmnem-sp_fmnem][0] ; ptr++ ) {
|
||||
if ( strcmp(*ptr,str)==0 ) return (ptr-em_mnem) ;
|
||||
}
|
||||
error("Illegal mnemonic") ;
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
error(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
|
||||
if ( !atend ) fprintf(stderr,"line %d: ",line) ;
|
||||
fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ;
|
||||
fprintf(stderr,"\n");
|
||||
nerror++ ;
|
||||
}
|
||||
|
||||
mess(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
|
||||
if ( !atend ) fprintf(stderr,"line %d: ",line) ;
|
||||
fprintf(stderr,str,a1,a2,a3,a4,a5,a6) ;
|
||||
fprintf(stderr,"\n");
|
||||
}
|
||||
|
||||
fatal(str,a1,a2,a3,a4,a5,a6) /* VARARGS1 */ char *str ; {
|
||||
error(str,a1,a2,a3,a4,a5,a6) ;
|
||||
exit(1) ;
|
||||
}
|
||||
|
||||
#define ILLGL -1
|
||||
|
||||
check(val) int val ; {
|
||||
if ( val!=ILLGL ) error("Illegal flag combination") ;
|
||||
}
|
||||
|
||||
int decflag(str) char *str ; {
|
||||
int type ;
|
||||
int escape ;
|
||||
int range ;
|
||||
int wordm ;
|
||||
int notzero ;
|
||||
|
||||
type=escape=range=wordm=notzero= ILLGL ;
|
||||
while ( *str ) switch ( *str++ ) {
|
||||
case 'm' :
|
||||
check(type) ; type=OPMINI ; break ;
|
||||
case 's' :
|
||||
check(type) ; type=OPSHORT ; break ;
|
||||
case '-' :
|
||||
check(type) ; type=OPNO ; break ;
|
||||
case '1' :
|
||||
check(type) ; type=OP8 ; break ;
|
||||
case '2' :
|
||||
check(type) ; type=OP16 ; break ;
|
||||
case '4' :
|
||||
check(type) ; type=OP32 ; break ;
|
||||
case '8' :
|
||||
check(type) ; type=OP64 ; break ;
|
||||
case 'u':
|
||||
check(type) ; type=OP16U ; break ;
|
||||
case 'e' :
|
||||
check(escape) ; escape=0 ; break ;
|
||||
case 'N' :
|
||||
check(range) ; range= 2 ; break ;
|
||||
case 'P' :
|
||||
check(range) ; range= 1 ; break ;
|
||||
case 'w' :
|
||||
check(wordm) ; wordm=0 ; break ;
|
||||
case 'o' :
|
||||
check(notzero) ; notzero=0 ; break ;
|
||||
default :
|
||||
error("Unknown flag") ;
|
||||
}
|
||||
if ( type==ILLGL ) error("Type must be specified") ;
|
||||
switch ( type ) {
|
||||
case OP64 :
|
||||
case OP32 :
|
||||
if ( escape!=ILLGL ) error("Conflicting escapes") ;
|
||||
escape=ILLGL ;
|
||||
case OP16 :
|
||||
case OP16U :
|
||||
case OP8 :
|
||||
case OPSHORT :
|
||||
case OPNO :
|
||||
if ( notzero!=ILLGL ) mess("Improbable OPNZ") ;
|
||||
if ( type==OPNO && range!=ILLGL ) {
|
||||
mess("No operand in range") ;
|
||||
}
|
||||
}
|
||||
if ( escape!=ILLGL ) type|=OPESC ;
|
||||
if ( wordm!=ILLGL ) type|=OPWORD ;
|
||||
switch ( range) {
|
||||
case ILLGL : type|=OP_BOTH ;
|
||||
if ( type==OPMINI || type==OPSHORT )
|
||||
error("Minies and shorties must have P or N") ;
|
||||
break ;
|
||||
case 1 : type|=OP_POS ; break ;
|
||||
case 2 : type|=OP_NEG ; break ;
|
||||
}
|
||||
if ( notzero!=ILLGL ) type|=OPNZ ;
|
||||
return type ;
|
||||
}
|
||||
|
||||
writeout() {
|
||||
register struct opform *next ;
|
||||
int elem[sp_lmnem-sp_fmnem+1+1] ;
|
||||
/* for each op points to first of descr. */
|
||||
register int i,currop ;
|
||||
int nch ;
|
||||
int compare() ;
|
||||
|
||||
qsort(intable,(lastform-intable)+1,sizeof intable[0],compare) ;
|
||||
|
||||
printf("int\tmaxinsl\t= %d ;\n",maxinsl) ;
|
||||
currop= -1 ; nch=0 ;
|
||||
printf("char opchoice[] = {\n") ;
|
||||
for (next=intable ; next<=lastform ; next++ ) {
|
||||
if ( (next->i_opcode&0377)!=currop ) {
|
||||
for ( currop++ ;
|
||||
currop<(next->i_opcode&0377) ; currop++ ) {
|
||||
elem[currop]= nch ;
|
||||
error("Missing opcode %s",em_mnem[currop]) ;
|
||||
}
|
||||
elem[currop]= nch ;
|
||||
}
|
||||
printf("%d, %d,",next->i_flag&0377,next->i_low&0377) ;
|
||||
nch+=2 ;
|
||||
switch ( next->i_flag&OPTYPE ) {
|
||||
case OPMINI :
|
||||
case OPSHORT :
|
||||
printf("%d,",next->i_num&0377) ; nch++ ;
|
||||
}
|
||||
printf("\n") ;
|
||||
}
|
||||
for ( currop++ ; currop<=sp_lmnem-sp_fmnem ; currop++ ) {
|
||||
elem[currop]= nch ;
|
||||
error("Missing opcode %s",em_mnem[currop]) ;
|
||||
}
|
||||
elem[sp_lmnem-sp_fmnem+1]=nch ;
|
||||
printf("0 } ;\n\nchar *opindex[] = {\n");
|
||||
for ( i=0 ; i<=sp_lmnem-sp_fmnem+1 ; i++ ) {
|
||||
printf(" &opchoice[%d],\n",elem[i]) ;
|
||||
}
|
||||
printf("} ;\n") ;
|
||||
}
|
||||
|
||||
int compare(a,b) struct opform *a,*b ; {
|
||||
if ( a->i_opcode!=b->i_opcode ) {
|
||||
return (a->i_opcode&0377)-(b->i_opcode&0377) ;
|
||||
}
|
||||
return oplength(a)-oplength(b) ;
|
||||
}
|
||||
|
||||
int oplength(a) struct opform *a ; {
|
||||
int cnt ;
|
||||
|
||||
cnt=1 ;
|
||||
if ( a->i_flag&OPESC ) cnt++ ;
|
||||
switch( a->i_flag&OPTYPE ) {
|
||||
case OPNO :
|
||||
case OPMINI : break ;
|
||||
case OP8 :
|
||||
case OPSHORT : cnt++ ; break ;
|
||||
case OP16U :
|
||||
case OP16 : cnt+=2 ; break ;
|
||||
case OP32 : cnt+=5 ; break ;
|
||||
case OP64 : cnt+=9 ; break ;
|
||||
}
|
||||
return cnt ;
|
||||
}
|
||||
|
||||
/* ----------- checking --------------*/
|
||||
|
||||
int ecodes[256],codes[256],lcodes[256] ;
|
||||
|
||||
#define NMNEM (sp_lmnem-sp_fmnem+1)
|
||||
#define MUST 1
|
||||
#define MAY 2
|
||||
#define FORB 3
|
||||
|
||||
char negc[NMNEM], zc[NMNEM], posc[NMNEM] ;
|
||||
|
||||
checkall() {
|
||||
register i,flag ;
|
||||
register struct opform *next ;
|
||||
int opc,low ;
|
||||
|
||||
for ( i=0 ; i<NMNEM ; i++ ) negc[i]=zc[i]=posc[i]=0 ;
|
||||
for ( i=0 ; i<256 ; i++ ) lcodes[i]= codes[i]= ecodes[i]= -1 ;
|
||||
codes[254]=codes[255]=ESCAP;
|
||||
|
||||
atend=0 ; line=0 ;
|
||||
for ( next=intable ; next<=lastform ; next++ ) {
|
||||
line++ ;
|
||||
flag = next->i_flag&0377 ;
|
||||
opc = next->i_opcode&0377 ;
|
||||
low = next->i_low&0377 ;
|
||||
chkc(flag,low,opc) ;
|
||||
switch(flag&OPTYPE) {
|
||||
case OPNO : zc[opc]++ ; break ;
|
||||
case OPMINI :
|
||||
case OPSHORT :
|
||||
for ( i=1 ; i<((next->i_num)&0377) ; i++ ) {
|
||||
chkc(flag,low+i,opc) ;
|
||||
}
|
||||
if ( !(em_flag[opc]&PAR_G) &&
|
||||
(flag&OPRANGE)==OP_BOTH) {
|
||||
mess("Mini's and shorties should have P or N");
|
||||
}
|
||||
break ;
|
||||
case OP8 :
|
||||
error("OP8 is removed") ;
|
||||
break ;
|
||||
case OP16 :
|
||||
if ( flag&OP_NEG )
|
||||
negc[opc]++ ;
|
||||
else if ( flag&OP_POS )
|
||||
posc[opc]++ ;
|
||||
break ;
|
||||
case OP16U :
|
||||
case OP32 :
|
||||
case OP64 :
|
||||
break ;
|
||||
default :
|
||||
error("Illegal type") ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
atend=1 ;
|
||||
for ( i=0 ; i<256 ; i++ ) if ( codes[i]== -1 ) {
|
||||
mess("interpreter opcode %d not used",i) ;
|
||||
}
|
||||
for ( opc=0 ; opc<NMNEM ; opc++ ) {
|
||||
switch(em_flag[opc]&EM_PAR) {
|
||||
case PAR_NO :
|
||||
ckop(opc,MUST,FORB,FORB) ;
|
||||
break ;
|
||||
case PAR_C:
|
||||
case PAR_D:
|
||||
case PAR_F:
|
||||
case PAR_B:
|
||||
ckop(opc,FORB,MAY,MAY) ;
|
||||
break ;
|
||||
case PAR_N:
|
||||
case PAR_G:
|
||||
case PAR_S:
|
||||
case PAR_Z:
|
||||
case PAR_O:
|
||||
case PAR_P:
|
||||
ckop(opc,FORB,MAY,FORB) ;
|
||||
break ;
|
||||
case PAR_R:
|
||||
ckop(opc,FORB,MAY,FORB) ;
|
||||
break ;
|
||||
case PAR_L:
|
||||
ckop(opc,FORB,MUST,MUST) ;
|
||||
break ;
|
||||
case PAR_W:
|
||||
ckop(opc,MUST,MAY,FORB) ;
|
||||
break ;
|
||||
default :
|
||||
error("Unknown instruction type of %s",ename(opc)) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
chkc(flag,icode,emc) {
|
||||
if ( flag&OPESC ) {
|
||||
if ( ecodes[icode]!=-1 ) {
|
||||
mess("Escaped opcode %d used by %s and %s",
|
||||
icode,ename(emc),ename(ecodes[icode])) ;
|
||||
}
|
||||
ecodes[icode]=emc;
|
||||
} else switch ( flag&OPTYPE ) {
|
||||
default:
|
||||
if ( codes[icode]!=-1 ) {
|
||||
mess("Opcode %d used by %s and %s",
|
||||
icode,ename(emc),ename(codes[icode])) ;
|
||||
}
|
||||
codes[icode]=emc;
|
||||
break ;
|
||||
case OP32:
|
||||
case OP64:
|
||||
if ( lcodes[icode]!=-1 ) {
|
||||
mess("Long opcode %d used by %s and %s",
|
||||
icode,ename(emc),ename(codes[icode])) ;
|
||||
}
|
||||
lcodes[icode]=emc;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
ckop(emc,zf,pf,nf) {
|
||||
if ( zc[emc]>1 ) mess("More then one OPNO for %s",ename(emc)) ;
|
||||
if ( posc[emc]>1 ) mess("More then one OP16(pos) for %s",ename(emc)) ;
|
||||
if ( negc[emc]>1 ) mess("More then one OP16(neg) for %s",ename(emc)) ;
|
||||
switch(zf) {
|
||||
case MUST:
|
||||
if ( zc[emc]==0 ) mess("No OPNO for %s",ename(emc)) ;
|
||||
break ;
|
||||
case FORB:
|
||||
if ( zc[emc]==1 ) mess("Forbidden OPNO for %s",ename(emc)) ;
|
||||
break ;
|
||||
}
|
||||
switch(pf) {
|
||||
case MUST:
|
||||
if ( posc[emc]==0 ) mess("No OP16(pos) for %s",ename(emc)) ;
|
||||
break ;
|
||||
case FORB:
|
||||
if ( posc[emc]==1 )
|
||||
mess("Forbidden OP16(pos) for %s",ename(emc)) ;
|
||||
break ;
|
||||
}
|
||||
switch(nf) {
|
||||
case MUST:
|
||||
if ( negc[emc]==0 ) mess("No OP16(neg) for %s",ename(emc)) ;
|
||||
break ;
|
||||
case FORB:
|
||||
if ( negc[emc]==1 )
|
||||
mess("Forbidden OP16(neg) for %s",ename(emc)) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
static int pushchar ;
|
||||
static int pushf ;
|
||||
|
||||
int readchar() {
|
||||
int c ;
|
||||
|
||||
if ( pushf ) {
|
||||
pushf=0 ;
|
||||
c = pushchar ;
|
||||
} else {
|
||||
if ( feof(stdin) ) return EOF ;
|
||||
c=getc(stdin) ;
|
||||
}
|
||||
if ( c=='\n' ) line++ ;
|
||||
return c ;
|
||||
}
|
||||
|
||||
pushback(c) {
|
||||
if ( pushf ) {
|
||||
fatal("Double pushback") ;
|
||||
}
|
||||
pushf++ ;
|
||||
pushchar=c ;
|
||||
if ( c=='\n' ) line-- ;
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
# $Id$
|
||||
|
||||
#PARAMS do not remove this line!
|
||||
|
||||
SRC_DIR = $(SRC_HOME)/util/ass
|
||||
INCLUDES = -I$(TARGET_HOME)/h -I$(TARGET_HOME)/config -I$(SRC_DIR)
|
||||
CFLAGS= $(INCLUDES) $(COPTIONS)
|
||||
UCFLAGS= $(INCLUDES) $(UCOPTIONS)
|
||||
LDFLAGS = $(LDOPTIONS)
|
||||
ULDFLAGS = $(ULDOPTIONS)
|
||||
LINTFLAGS = $(INCLUDES) $(LINTOPTIONS)
|
||||
|
||||
OBS = ass00.$(SUF) ass30.$(SUF) ass40.$(SUF) ass50.$(SUF) ass60.$(SUF) \
|
||||
ass70.$(SUF) ass80.$(SUF) assci.$(SUF) assda.$(SUF) assrl.$(SUF) \
|
||||
asstb.$(SUF) asscm.$(SUF)
|
||||
CFILES = $(SRC_DIR)/ass00.c $(SRC_DIR)/ass30.c $(SRC_DIR)/ass40.c \
|
||||
$(SRC_DIR)/ass50.c $(SRC_DIR)/ass60.c $(SRC_DIR)/ass70.c \
|
||||
$(SRC_DIR)/ass80.c $(SRC_DIR)/assci.c $(SRC_DIR)/assda.c \
|
||||
$(SRC_DIR)/assrl.c asstb.c $(SRC_DIR)/asscm.c
|
||||
|
||||
all: ass
|
||||
|
||||
clean:
|
||||
-rm -f ass *.$(SUF) maktab *.old asstb.c
|
||||
|
||||
install : all
|
||||
cp ass $(TARGET_HOME)/lib.bin/em_ass
|
||||
if [ $(DO_MACHINE_INDEP) = y ] ; \
|
||||
then mk_manpage $(SRC_DIR)/em_ass.6 $(TARGET_HOME) ; \
|
||||
fi
|
||||
|
||||
cmp : all
|
||||
-cmp ass $(TARGET_HOME)/lib.bin/em_ass
|
||||
|
||||
lint: asstb.c
|
||||
$(LINT) $(LINTFLAGS) $(CFILES)
|
||||
|
||||
ass: $(OBS)
|
||||
$(CC) $(LDFLAGS) -o ass $(OBS) $(TARGET_HOME)/lib.bin/em_data.$(LIBSUF)
|
||||
|
||||
asstb.c: maktab $(SRC_HOME)/etc/ip_spec.t
|
||||
maktab $(SRC_HOME)/etc/ip_spec.t asstb.c
|
||||
|
||||
maktab: $(SRC_DIR)/maktab.c $(TARGET_HOME)/h/ip_spec.h
|
||||
$(UCC) $(ULDFLAGS) $(UCFLAGS) -o maktab $(SRC_DIR)/maktab.c $(UTIL_HOME)/lib.bin/em_data.$(ULIBSUF)
|
||||
|
||||
asprint: $(SRC_DIR)/asprint.p
|
||||
apc -w -o asprint $(SRC_DIR)/asprint.p
|
||||
|
||||
opr:
|
||||
make pr ^ opr
|
||||
|
||||
pr:
|
||||
@pr $(SRC_DIR)/ass00.h $(SRC_DIR)/assex.h $(SRC_DIR)/ass?0.c $(SRC_DIR)/ass[rcd]?.c $(SRC_DIR)/maktab.c
|
||||
|
||||
depend: asstb.c
|
||||
rm_deps Makefile >Makefile.new
|
||||
for i in $(CFILES) ; do \
|
||||
echo "`basename $$i .c`.$$(SUF): $$i" >> Makefile.new ; \
|
||||
echo ' $$(CC) -c $$(CFLAGS)' $$i >> Makefile.new ; \
|
||||
$(UTIL_HOME)/lib.bin/cpp -d $(INCLUDES) $$i | sed "s/^/`basename $$i .c`.$$(SUF): /" >> Makefile.new ; \
|
||||
done
|
||||
mv Makefile Makefile.old
|
||||
mv Makefile.new Makefile
|
||||
|
||||
# do not remove the next line.
|
||||
#DEPENDENCIES
|
||||
ass00.$(SUF): $(SRC_DIR)/ass00.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/ass00.c
|
||||
ass00.$(SUF): $(SRC_DIR)/assex.h
|
||||
ass00.$(SUF): $(TARGET_HOME)/config/local.h
|
||||
ass00.$(SUF): $(TARGET_HOME)/h/arch.h
|
||||
ass00.$(SUF): $(TARGET_HOME)/h/em_flag.h
|
||||
ass00.$(SUF): $(TARGET_HOME)/h/as_spec.h
|
||||
ass00.$(SUF): $(TARGET_HOME)/h/em_spec.h
|
||||
ass00.$(SUF): $(SRC_DIR)/ass00.h
|
||||
ass30.$(SUF): $(SRC_DIR)/ass30.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/ass30.c
|
||||
ass30.$(SUF): $(TARGET_HOME)/h/ip_spec.h
|
||||
ass30.$(SUF): $(SRC_DIR)/assex.h
|
||||
ass30.$(SUF): $(TARGET_HOME)/config/local.h
|
||||
ass30.$(SUF): $(TARGET_HOME)/h/arch.h
|
||||
ass30.$(SUF): $(TARGET_HOME)/h/em_flag.h
|
||||
ass30.$(SUF): $(TARGET_HOME)/h/as_spec.h
|
||||
ass30.$(SUF): $(TARGET_HOME)/h/em_spec.h
|
||||
ass30.$(SUF): $(SRC_DIR)/ass00.h
|
||||
ass40.$(SUF): $(SRC_DIR)/ass40.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/ass40.c
|
||||
ass40.$(SUF): $(SRC_DIR)/assex.h
|
||||
ass40.$(SUF): $(TARGET_HOME)/config/local.h
|
||||
ass40.$(SUF): $(TARGET_HOME)/h/arch.h
|
||||
ass40.$(SUF): $(TARGET_HOME)/h/em_flag.h
|
||||
ass40.$(SUF): $(TARGET_HOME)/h/as_spec.h
|
||||
ass40.$(SUF): $(TARGET_HOME)/h/em_spec.h
|
||||
ass40.$(SUF): $(SRC_DIR)/ass00.h
|
||||
ass50.$(SUF): $(SRC_DIR)/ass50.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/ass50.c
|
||||
ass50.$(SUF): $(TARGET_HOME)/h/ip_spec.h
|
||||
ass50.$(SUF): $(SRC_DIR)/assex.h
|
||||
ass50.$(SUF): $(TARGET_HOME)/config/local.h
|
||||
ass50.$(SUF): $(TARGET_HOME)/h/arch.h
|
||||
ass50.$(SUF): $(TARGET_HOME)/h/em_flag.h
|
||||
ass50.$(SUF): $(TARGET_HOME)/h/as_spec.h
|
||||
ass50.$(SUF): $(TARGET_HOME)/h/em_spec.h
|
||||
ass50.$(SUF): $(SRC_DIR)/ass00.h
|
||||
ass60.$(SUF): $(SRC_DIR)/ass60.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/ass60.c
|
||||
ass60.$(SUF): $(TARGET_HOME)/h/ip_spec.h
|
||||
ass60.$(SUF): $(SRC_DIR)/assex.h
|
||||
ass60.$(SUF): $(TARGET_HOME)/config/local.h
|
||||
ass60.$(SUF): $(TARGET_HOME)/h/arch.h
|
||||
ass60.$(SUF): $(TARGET_HOME)/h/em_flag.h
|
||||
ass60.$(SUF): $(TARGET_HOME)/h/as_spec.h
|
||||
ass60.$(SUF): $(TARGET_HOME)/h/em_spec.h
|
||||
ass60.$(SUF): $(SRC_DIR)/ass00.h
|
||||
ass70.$(SUF): $(SRC_DIR)/ass70.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/ass70.c
|
||||
ass70.$(SUF): $(SRC_DIR)/assex.h
|
||||
ass70.$(SUF): $(TARGET_HOME)/config/local.h
|
||||
ass70.$(SUF): $(TARGET_HOME)/h/arch.h
|
||||
ass70.$(SUF): $(TARGET_HOME)/h/em_flag.h
|
||||
ass70.$(SUF): $(TARGET_HOME)/h/as_spec.h
|
||||
ass70.$(SUF): $(TARGET_HOME)/h/em_spec.h
|
||||
ass70.$(SUF): $(SRC_DIR)/ass00.h
|
||||
ass80.$(SUF): $(SRC_DIR)/ass80.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/ass80.c
|
||||
ass80.$(SUF): $(TARGET_HOME)/config/em_path.h
|
||||
ass80.$(SUF): $(SRC_DIR)/assex.h
|
||||
ass80.$(SUF): $(TARGET_HOME)/config/local.h
|
||||
ass80.$(SUF): $(TARGET_HOME)/h/arch.h
|
||||
ass80.$(SUF): $(TARGET_HOME)/h/em_flag.h
|
||||
ass80.$(SUF): $(TARGET_HOME)/h/as_spec.h
|
||||
ass80.$(SUF): $(TARGET_HOME)/h/em_spec.h
|
||||
ass80.$(SUF): $(SRC_DIR)/ass00.h
|
||||
assci.$(SUF): $(SRC_DIR)/assci.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/assci.c
|
||||
assci.$(SUF): $(TARGET_HOME)/h/em_ptyp.h
|
||||
assci.$(SUF): $(TARGET_HOME)/h/em_pseu.h
|
||||
assci.$(SUF): $(TARGET_HOME)/h/em_mes.h
|
||||
assci.$(SUF): $(SRC_DIR)/assex.h
|
||||
assci.$(SUF): $(TARGET_HOME)/config/local.h
|
||||
assci.$(SUF): $(TARGET_HOME)/h/arch.h
|
||||
assci.$(SUF): $(TARGET_HOME)/h/em_flag.h
|
||||
assci.$(SUF): $(TARGET_HOME)/h/as_spec.h
|
||||
assci.$(SUF): $(TARGET_HOME)/h/em_spec.h
|
||||
assci.$(SUF): $(SRC_DIR)/ass00.h
|
||||
assda.$(SUF): $(SRC_DIR)/assda.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/assda.c
|
||||
assda.$(SUF): $(SRC_DIR)/assex.h
|
||||
assda.$(SUF): $(TARGET_HOME)/config/local.h
|
||||
assda.$(SUF): $(TARGET_HOME)/h/arch.h
|
||||
assda.$(SUF): $(TARGET_HOME)/h/em_flag.h
|
||||
assda.$(SUF): $(TARGET_HOME)/h/as_spec.h
|
||||
assda.$(SUF): $(TARGET_HOME)/h/em_spec.h
|
||||
assda.$(SUF): $(SRC_DIR)/ass00.h
|
||||
assrl.$(SUF): $(SRC_DIR)/assrl.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/assrl.c
|
||||
assrl.$(SUF): $(SRC_DIR)/assex.h
|
||||
assrl.$(SUF): $(TARGET_HOME)/config/local.h
|
||||
assrl.$(SUF): $(TARGET_HOME)/h/arch.h
|
||||
assrl.$(SUF): $(TARGET_HOME)/h/em_flag.h
|
||||
assrl.$(SUF): $(TARGET_HOME)/h/as_spec.h
|
||||
assrl.$(SUF): $(TARGET_HOME)/h/em_spec.h
|
||||
assrl.$(SUF): $(SRC_DIR)/ass00.h
|
||||
asstb.$(SUF): asstb.c
|
||||
$(CC) -c $(CFLAGS) asstb.c
|
||||
asscm.$(SUF): $(SRC_DIR)/asscm.c
|
||||
$(CC) -c $(CFLAGS) $(SRC_DIR)/asscm.c
|
||||
asscm.$(SUF): $(TARGET_HOME)/config/local.h
|
||||
asscm.$(SUF): $(TARGET_HOME)/h/arch.h
|
||||
asscm.$(SUF): $(TARGET_HOME)/h/em_flag.h
|
||||
asscm.$(SUF): $(TARGET_HOME)/h/as_spec.h
|
||||
asscm.$(SUF): $(TARGET_HOME)/h/em_spec.h
|
||||
asscm.$(SUF): $(SRC_DIR)/ass00.h
|
||||
@@ -1,19 +0,0 @@
|
||||
ACKNOWLEDGEMENTS
|
||||
proto.make
|
||||
NEW_FEATURES
|
||||
NO_WARRANTY
|
||||
README
|
||||
closure.c
|
||||
defs.h
|
||||
error.c
|
||||
lalr.c
|
||||
lr0.c
|
||||
main.c
|
||||
manpage
|
||||
mkpar.c
|
||||
output.c
|
||||
reader.c
|
||||
skeleton.c
|
||||
symtab.c
|
||||
verbose.c
|
||||
warshall.c
|
||||
@@ -1,25 +0,0 @@
|
||||
Berkeley Yacc owes much to the unflagging efforts of Keith Bostic.
|
||||
His badgering kept me working on it long after I was ready to quit.
|
||||
|
||||
Berkeley Yacc is based on the excellent algorithm for computing LALR(1)
|
||||
lookaheads developed by Tom Pennello and Frank DeRemer. The algorithm is
|
||||
described in their almost impenetrable article in TOPLAS 4,4.
|
||||
|
||||
Finally, much of the credit for the latest version must go to those
|
||||
who pointed out deficiencies of my earlier releases. Among the most
|
||||
prolific contributors were
|
||||
|
||||
Benson I. Margulies
|
||||
Dave Gentzel
|
||||
Antoine Verheijen
|
||||
Peter S. Housel
|
||||
Dale Smith
|
||||
Ozan Yigit
|
||||
John Campbell
|
||||
Bill Sommerfeld
|
||||
Paul Hilfinger
|
||||
Gary Bridgewater
|
||||
Dave Bakken
|
||||
Dan Lanciani
|
||||
Richard Sargent
|
||||
Parag Patel
|
||||
@@ -1,82 +0,0 @@
|
||||
EMHOME = ../..
|
||||
|
||||
DEST = $(EMHOME)/bin
|
||||
MAN = $(EMHOME)/man
|
||||
|
||||
HDRS = defs.h
|
||||
|
||||
CFLAGS = -O -Dvoid=int
|
||||
|
||||
LDFLAGS =
|
||||
|
||||
LIBS =
|
||||
|
||||
LINKER = cc
|
||||
|
||||
OBJS = closure.o \
|
||||
error.o \
|
||||
lalr.o \
|
||||
lr0.o \
|
||||
main.o \
|
||||
mkpar.o \
|
||||
output.o \
|
||||
reader.o \
|
||||
skeleton.o \
|
||||
symtab.o \
|
||||
verbose.o \
|
||||
warshall.o
|
||||
|
||||
PRINT = pr -f -l88
|
||||
|
||||
PROGRAM = yacc
|
||||
|
||||
SRCS = closure.c \
|
||||
error.c \
|
||||
lalr.c \
|
||||
lr0.c \
|
||||
main.c \
|
||||
mkpar.c \
|
||||
output.c \
|
||||
reader.c \
|
||||
skeleton.c \
|
||||
symtab.c \
|
||||
verbose.c \
|
||||
warshall.c
|
||||
|
||||
all: $(PROGRAM)
|
||||
|
||||
$(PROGRAM): $(OBJS) $(LIBS)
|
||||
@echo -n "Loading $(PROGRAM) ... "
|
||||
@$(LINKER) $(LDFLAGS) -o $(PROGRAM) $(OBJS) $(LIBS)
|
||||
@echo "done"
|
||||
|
||||
clean:; @rm -f $(OBJS) $(PROGRAM)
|
||||
|
||||
index:; @ctags -wx $(HDRS) $(SRCS)
|
||||
|
||||
install: $(PROGRAM)
|
||||
@echo Installing $(PROGRAM) in $(DEST)
|
||||
cp $(PROGRAM) $(DEST)/$(PROGRAM)
|
||||
cp manpage $(MAN)/yacc.1
|
||||
|
||||
listing:; @$(PRINT) Makefile $(HDRS) $(SRCS) | lpr
|
||||
|
||||
lint:; @lint $(SRCS)
|
||||
|
||||
program: $(PROGRAM)
|
||||
|
||||
tags: $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS)
|
||||
|
||||
###
|
||||
closure.o: defs.h
|
||||
error.o: defs.h
|
||||
lalr.o: defs.h
|
||||
lr0.o: defs.h
|
||||
main.o: defs.h
|
||||
mkpar.o: defs.h
|
||||
output.o: defs.h
|
||||
reader.o: defs.h
|
||||
skeleton.o: defs.h
|
||||
symtab.o: defs.h
|
||||
verbose.o: defs.h
|
||||
warshall.o: defs.h
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user