fixup commit for tag 'oct-1'

This commit is contained in:
cvs2hg
1994-12-06 09:12:22 +00:00
parent 7393f8923c
commit dc2a339e09
8241 changed files with 0 additions and 694108 deletions

View File

@@ -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

View File

@@ -1,7 +0,0 @@
READ_ME
COPYING
lib
src
Makefile
proto.make
LLgen.1

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -1,2 +0,0 @@
incl
rec

View File

@@ -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 */

View File

@@ -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];
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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 */
};

View File

@@ -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

View File

@@ -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,' ');
}

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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[];

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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++;
}
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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 = &ltext[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;
}
}
}

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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[] ;

View File

@@ -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 ;
}

View File

@@ -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 ;
}

View File

@@ -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 */

View File

@@ -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 ;
}

View File

@@ -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) )

View File

@@ -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 ;
}
}

View File

@@ -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

View File

@@ -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) ;
}

View File

@@ -1,2 +0,0 @@
Makefile
em_pc.c

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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 ;
}

View File

@@ -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 ;
}

View File

@@ -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") ;
}

View File

@@ -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 ;
}

View File

@@ -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) ;
}

View File

@@ -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))

View File

@@ -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 ;
}

View File

@@ -1,8 +0,0 @@
proto.make
anm.c
asize.c
astrip.c
ashow.c
anm.1
asize.1
astrip.1

View File

@@ -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

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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(&section, 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);
}

View File

@@ -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)

View File

@@ -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);
}

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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

View File

@@ -1,5 +0,0 @@
proto.make
aal.1
arch.1
arch.5
archiver.c

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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 */

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -1,2 +0,0 @@
- make the tables that still have a fixed length of dynamically varying
length, and remove the size options

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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 */
};

View File

@@ -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 */
}
}

View File

@@ -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 ;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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 ;
}

View File

@@ -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

View File

@@ -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 */

View File

@@ -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

View File

@@ -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 ;
}

View File

@@ -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

View File

@@ -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 */

View File

@@ -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-- ;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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