fixup commit for branch 'unlabeled-2.2.1'

This commit is contained in:
cvs2hg
1984-07-16 15:29:49 +00:00
parent 4410480e32
commit b5c00dbbf4
231 changed files with 0 additions and 64000 deletions

View File

@@ -1,23 +0,0 @@
Makefile
ack.h
data.c
data.h
dmach.c
dmach.h
files.c
grows.c
grows.h
intable.c
list.c
list.h
main.c
malloc.c
mktables.c
pc
rmach.c
run.c
scan.c
svars.c
trans.c
trans.h
util.c

View File

@@ -1,63 +0,0 @@
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=../../lib/ack
FE=fe
INTABLES=pdp int
LNTABLES=6500 m68k2 m68k4 6809 8080 acc apc nascom vax2 vax4 z80 i86
CFLAGS=-O -n
BINDIR=../../bin
head: ack
install: ack
cp ack $(BINDIR)/ack
-cd $(BINDIR) ; \
for i in $(INTABLES) $(LNTABLES) ; do ln ack $$i ; done
(cd pc ; make install )
cmp: ack
cmp ack $(BINDIR)/ack
(cd pc ; make cmp )
clean:
-rm -f *.old *.o ack
(cd pc ; make clean )
ack: $(OBJ)
$(CC) -o ack $(CFLAGS) $(OBJ)
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 : ../../h/em_path.h
main.o : ../../h/local.h
malloc.o 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) $(ACKDIR)/*
@(cd pc ; make pr)
opr:
make pr | opr
lint: $(ISRC)
lint -hbx $(DSRC) $(ISRC)

View File

@@ -1,260 +0,0 @@
.\" $Header$
.TH ACK I
.ad
.SH NAME
ack \- Amsterdam Compiler Kit
.SH SYNOPSIS
\fBack\fP arguments
.br
\fBacc\fP arguments
.br
\fBapc\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.
Compilation time for interpretation is fast and gives many
runtime checks,
but execution is about seven times slower.
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 load file.
.PP
\fIAck\fP recognizes the following suffixes:
.IP .p
Pascal program.
.IP .c
C 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:
.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 \-m8086 file.p\fP is equivalent to \fI8086
file.p\fP.
.IP \-o
The the next argument as the name of the resulting load file,
instead of the default \fIa.out\fP or \fIe.out\fP.
.IP \-O
Use the EM peephole optimizer,
this flag is superfluous when an machine code is generated.
.IP \-LIB
This flag tells the peephole optimizer
.RF em_opt VI
to add information about the visibility of the names used
to each output module.
This is needed by most
assembler/linkers when these modules are to be inserted
in 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 \-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 \-L
Disable the generation of code by the front ends to
record line number and source file name at run-time.
.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.
.IP \-w
Suppress all warning messages.
.IP \-v
Verbose.
Print information while juggling with files.
.IP \-g
Try to run the resulting load file.
No arguments can be passed this way,
so it is only useful in simple cases.
.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 \-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.
Note: \fIack\fP refuses to overwrite argument \fI.e\fP files.
.IP \-t
Preserve all intermediate files.
.IP \-k
Do not stop when an error occurs, but try to transform all
other arguments as far as possible.
.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 \-E
Produce a complete listing of each Pascal source program.
Normally for each error, one message,
including the source line number, is given.
.IP \-e
List only the erroneous lines of each Pascal source program.
.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 you want to interpret your program, you may 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, you give these
flag options each time you run the interpreter.
The EM assembler/linker gives you 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.
.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 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".
.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.
Other human readable sources (Pascal 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 and/or C compiler.
All sizes are in bytes.
.PP
.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
.PP
The name of the \fImachine\fP or something like it when
the machine name is numeric is also defined (as 1).
.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.
.TS
tab(:);
l l l l.
input:name:output:description
\&.c:cem:.k:C front end [4,5,6]
\&.p:pc:.k:Pascal front end [2,3,6]
\&.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:be:.s:backend
\&.s:asld:a.out:Assembler/linker producing machine code
\&.s:as:.o:Assembler
\&.o:ld:a.out:Linker producing machine code
.TE
.SH "SEE ALSO"
.PD 0
em_opt(VI), em_ass(VI), em_cg(VI)
.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.
.IP [2]
K. Jensen and N. Wirth
"PASCAL, User manual and report" 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]
E.G. Keizer, Amsterdam Compiler Kit, reference manuals and UNIX manual pages.
.PD
.SH DIAGNOSTICS
.PD
The diagnostics are intended to be self\-explanatory.
.SH BUGS
The -g flag is inoperative.
.br
Not all warning messages are superseded by \fB\-w\fP.
.br
Argument assembly files are not preprocessed when fed into the
universal assembler.
.SH AUTHOR
Ed Keizer, Vrije Universiteit, Amsterdam

View File

@@ -1,88 +0,0 @@
/****************************************************************************/
/* User settable options */
/****************************************************************************/
#define FRONTENDS "fe" /* The front-end definitions */
#define ACKNAME "AckXXXXXX" /* Handed to mktemp for temp. files */
/****************************************************************************/
/* Internal mnemonics, should not be tinkered with */
/****************************************************************************/
/* The names of some string variables */
#define HOME "EM"
#define RTS "RTS"
#define NEEDS "NEEDS"
#define HEAD "HEAD"
#define TAIL "TAIL"
#define SRC "SOURCE"
#define LIBVAR "LNAME"
/* 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 ;
/* Return values of setpath() */
enum f_path { F_OK, F_NOMATCH, F_NOPATH } ;
/* Library routines */
extern char *index();
extern char *rindex();
extern char *strcpy();
extern char *strcat();
extern char *mktemp();
extern int unlink();
extern int close();
extern int open();
extern int creat();
/* Own routines */
enum f_path setpath();
enum f_path scan_end();
extern int 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,9 +0,0 @@
#include "ack.h"
#include "list.h"
#include "trans.h"
#undef EXTERN
#define EXTERN
#include "data.h"

View File

@@ -1,43 +0,0 @@
EXTERN char *stopsuffix; /* Suffix to stop at */
EXTERN char *machine; /* The machine id */
EXTERN char *rts; /* The runtime-system id */
EXTERN list_head arguments; /* List of arguments */
EXTERN list_head flags; /* List of flags */
EXTERN list_head c_arguments; /* List of linker arguments */
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 g_flag; /* do_run() */
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 file names */
EXTERN int Optflag; /* 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; /* The template for temporary file
names */
EXTERN trf *combiner; /* Pointer to the Loader/Linker */
EXTERN trf *cpp_trafo; /* Pointer to C-preprocessor */
EXTERN path in; /* The current 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,15 +0,0 @@
/***************************************************************/
/* */
/* Definition for table that maps a name on an intable index */
/* */
/***************************************************************/
typedef struct {
char *ma_name ; /* The name of the machine */
int ma_index ;
} dmach ;
extern dmach massoc[] ;
extern char intable[] ;

View File

@@ -1,94 +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"
#include "list.h"
#include "trans.h"
#include "grows.h"
#include "data.h"
#include "../../h/em_path.h"
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 ;
if ( phase->t_combine ) {
out.p_keep=YES ;
out.p_path=outfile ;
out.p_keeps=NO ;
in.p_path= (char *)0 ;
in.p_keep=YES ;
in.p_keeps=NO ;
} else {
gr_init(&pathname) ;
if ( !phase->t_keep && !t_flag ) {
gr_cat(&pathname,TMP_DIR) ;
gr_cat(&pathname,"/") ;
gr_cat(&pathname,template) ;
out.p_keep=NO ;
} 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 argument file") ;
return 0 ;
}
}
return 1 ;
}
disc_files() {
if ( in.p_path ) {
if ( !in.p_keep ) {
if ( unlink(in.p_path)!=0 ) {
werror("couldn't unlink %s",in.p_path);
}
}
if ( in.p_keeps ) throws(in.p_path) ;
}
in=out ;
out.p_path= (char *)0 ;
out.p_keeps=NO ;
out.p_keep=NO ;
}
rmtemps() {
/* Called in case of disaster, always remove the current output file!
*/
if ( out.p_path ) {
unlink(out.p_path) ;
if ( out.p_keeps ) throws(out.p_path) ;
out.p_path= (char *)0 ;
out.p_keeps=NO ;
out.p_keep=NO ;
}
if ( !in.p_keep && in.p_path ) {
unlink(in.p_path) ;
if ( in.p_keeps ) throws(in.p_path) ;
in.p_path= (char *)0 ;
out.p_keeps= NO ;
out.p_keep=NO ;
}
}

View File

@@ -1,79 +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
*
*/
/**************************************************************************/
/* */
/* Bookkeeping for growing strings */
/* */
/**************************************************************************/
#include "ack.h"
#include "grows.h"
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_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,19 +0,0 @@
/* 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,73 +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"
#include "list.h"
/* 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_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,23 +0,0 @@
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,340 +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"
#include "list.h"
#include "trans.h"
#include "../../h/em_path.h"
#include "../../h/local.h"
#include "data.h"
#include <signal.h>
static int sigs[] = { SIGINT, SIGHUP, SIGTERM, 0 } ;
extern char *getenv();
main(argc,argv) char **argv ; {
register list_elem *elem ;
register char *frontend ;
register int *n_sig ;
progname=argv[0];
varinit();
vieuwargs(argc,argv);
if ( (frontend=getenv("ACKFE")) ) {
setlist(frontend) ;
} else {
setlist(FRONTENDS);
}
setlist(machine);
transini();
scanneeds();
template= mktemp(ACKNAME) ;
if ( n_error && !k_flag ) return 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 ) {
if ( !process(l_content(*elem)) && !k_flag ) return 1 ;
}
orig.p_path= (char *)0 ;
if ( !combiner && !stopsuffix ) {
/* Call combiner directly without any transformation */
scanlist(l_first(tr_list),elem) {
if ( t_cont(*elem)->t_combine ) {
combiner= t_cont(*elem) ;
}
}
}
if ( !combiner || n_error ) return n_error ;
if ( !do_combine() ) return 1 ;
if ( g_flag ) {
return do_run();
}
return 0 ;
}
char *srcvar() {
return orig.p_path ;
}
varinit() {
/* initialize the string variables */
setsvar(keeps(HOME),keeps(EM_DIR)) ;
setpvar(keeps(SRC),srcvar) ;
}
/************************* flag processing ***********************/
vieuwargs(argc,argv) char **argv ; {
register char *argp;
register int nextarg ;
register int eaten ;
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 */
eaten=0 ; /* Did not 'eat' tail of flag yet */
switch ( argp[1] ) {
case 'm': if ( machine ) fuerror("Two machines?") ;
machine= &argp[2];
eaten=1 ;
break ;
case 'o': if ( nextarg>=argc ) {
fuerror("-o can't be the last flag") ;
}
if ( outfile ) fuerror("Two results?") ;
outfile= argv[nextarg++] ;
break ;
case 'O': Optflag++ ;
break ;
case 'v': v_flag++ ;
break ;
case 'g': g_flag++ ;
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': do_Rflag(argp); 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 ) fuerror("Two run-time systems?") ;
rts= &argp[1] ; eaten=1;
keephead(rts) ; keeptail(rts) ;
break ;
#ifdef DEBUG
case 'd': debug++ ;
break ;
#endif
case 0 : nill_flag++ ; eaten++ ;
break;
case 'w': { register char *tokeep ;
w_flag++;
tokeep=keeps(argp) ;
*tokeep |= NO_SCAN ;
l_add(&flags,tokeep) ;
}
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 ;
}
if ( argp[2] && !eaten ) {
werror("Unexpected characters at end of %s",argp) ;
}
}
if ( !machine && ! (machine=getenv("ACKM")) ) {
#ifdef ACKM
machine= ACKM; /* The default machine */
#else
fuerror("No machine specified") ;
#endif
}
return ;
}
firstarg(argp) register char *argp ; {
register char *name ;
name=rindex(argp,'/') ;
if ( name && *(name+1) ) {
name++ ;
} else {
name= argp ;
}
if ( strcmp(name,"ack")==0 ) return ;
if ( strcmp(name,"acc")==0 || strcmp(name,"cc")==0 ) {
rts= ".c" ; keephead(rts) ; keeptail(rts) ;
return ;
}
if ( strcmp(name,"apc")==0 || strcmp(name,"pc")==0 ) {
rts= ".p" ; keephead(rts) ; keeptail(rts) ;
return ;
}
machine= name;
}
/************************* argument processing ***********************/
process(arg) char *arg ; {
/* Process files & library arguments */
register list_elem *elem ;
register trf *phase ;
int first=YES ;
#ifdef DEBUG
if ( debug ) vprint("Processing %s\n",arg) ;
#endif
if ( arg[0]=='-' ) { l_add(&c_arguments,keeps(arg)) ; return 1 ; }
p_suffix= rindex(arg,SUFCHAR) ;
if ( p_basename ) throws(p_basename) ;
orig.p_keep= YES ; /* Don't throw away the original ! */
orig.p_path= arg ;
p_basename= keeps(basename(arg)) ;
if ( !p_suffix ) { l_add(&c_arguments,keeps(arg)) ; return 1 ; }
/* Try to find a path through the transformations */
switch( setpath() ) {
case F_NOPATH :
error("Cannot produce the desired file from %s",arg) ;
l_add(&c_arguments,keeps(arg)) ;
return 1 ;
case F_NOMATCH :
if ( stopsuffix ) werror("Unknown suffix in %s",arg) ;
l_add(&c_arguments,keeps(arg)) ;
return 1 ;
case F_OK :
break ;
}
orig.p_keeps= NO;
in= orig ;
scanlist(l_first(tr_list), elem) {
phase= t_cont(*elem) ;
if ( phase->t_do ) { /* perform this transformation */
if ( first ) {
if ( !nill_flag ) {
printf("%s\n",arg) ;
}
}
switch ( phase->t_prep ) {
default : if ( !mayprep() ) break ;
case YES: if ( !transform(cpp_trafo) ) {
n_error++ ;
#ifdef DEBUG
vprint("Pre-processor failed\n") ;
#endif
return 0 ;
}
case NO :
break ;
}
if ( cpp_trafo && stopsuffix &&
strcmp(cpp_trafo->t_out,stopsuffix)==0 ) {
break ;
}
if ( !transform(phase) ) {
n_error++ ;
#ifdef DEBUG
if ( debug ) {
vprint("phase %s for %s failed\n",
phase->t_name,orig.p_path) ;
}
#endif
return 0 ;
}
first=NO ;
}
}
#ifdef DEBUG
if ( debug ) vprint("Transformation complete for %s\n",orig.p_path) ;
#endif
if ( !in.p_keep ) fatal("attempt to discard the result file") ;
l_add(&c_arguments,keeps(in.p_path));
disc_files() ;
return 1 ;
}
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 ; {
register list_elem *elem ;
register trf *phase ;
p_suffix= suffix ;
switch ( setpath() ) {
case F_OK :
scanlist( l_first(tr_list), elem ) {
phase = t_cont(*elem) ;
if ( phase->t_do ) {
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("incomplete internal specification for %s files",
suffix) ;
break ;
}
}

View File

@@ -1,208 +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
/* 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 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 <stdio.h>
#include <ctype.h>
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 ; {
strcpy(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,25 +0,0 @@
d=../../..
h=$d/h
PC_PATH=$d/lib/em_pc
em_pc: em_pc.c $h/local.h $h/em_path.h
cc -n -o em_pc -O -I$h em_pc.c
cmp: em_pc
cmp em_pc $(PC_PATH)
install: em_pc
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,681 +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
*
*/
/*
* 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 = PEM_PATH ;
char *err_path = ERR_PATH;
int toterr;
int parent;
char *eeflag;
char *vvflag = "-V";
int no_pemflag = 0 ;
char *pemflag[MAX_FLAG];
char *eflag;
char *wflag;
int sizes[sz_last+1] = {
2, /* sz_addr */
8, /* sz_real */
0, /* sz_head */
512, /* sz_buff */
4096, /* sz_mset */
2, /* sz_iset */
};
#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 *sbrk();
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':
vvflag = f;
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(f) FILE *f; {
register c, i;
register char *p;
p = vvflag + 2;
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':
case 'i': if (i == 2) continue; break;
case 'l': if (i == 4) continue; break;
}
fatal("bad V-flag %s",vvflag);
}
if (sz_head == 0)
sz_head = 6*sz_word + 2*sz_addr;
for (i = 0; i <= sz_last; i++)
fprintf(f, "%d\n",sizes[i]);
}
/* ------------------ calling sequences -------------------- */
pem(p,q) char *p,*q; {
register char **v,*d;
int i;
FILE *erfil;
v = initvector(pc_path);
d = tempfile('d');
if ((erfil = fopen(d,"w")) == NULL)
syserr(d);
initsizes(erfil);
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 *) sbrk(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);
if (ch == '#') {
if (lineline(printing) == 0)
fatal("bad line directive");
return(1);
}
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];
p = line;
while ((ch = getc(inpfil)) != '\n') {
if (ch == EOF || p == &line[100-1])
return(0);
*p++ = ch;
}
*p = '\0'; p = line;
if (printing)
printf("\t#%s\n",p);
if ((listrela = atoi(p)-1) < 0)
return(0);
while ((ch = *p++) != '"')
if (ch == '\0')
return(0);
q = p;
while (ch = *p++) {
if (ch == '"') {
*--p = '\0';
if ( source ) {
listfnam = strcmp(q,source)==0 ? source : q;
return(1);
}
source=q ; listfnam=q ;
return 1 ;
}
if (ch == '/')
q = 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 ((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,303 +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"
#include "../../h/em_path.h"
#include "list.h"
#include "trans.h"
#include "grows.h"
#include "dmach.h"
#include "data.h"
#include <stdio.h>
/************************************************************************/
/* */
/* Read machine definitions and transformations */
/* */
/************************************************************************/
#define COMMENT '#'
#define VAR "var"
#define PASS "name"
#define IN "from"
#define OUT "to"
#define PROG "program"
#define MAPF "mapflag"
#define ARGS "args"
#define PROP "prop"
#define RUNT "rts"
#define NEEDT "need"
#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(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
}
intrf() {
register trf *new ;
register char *ptr ;
growstring bline, vline ;
int twice ;
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 \ */
vline= scanvars(gr_start(bline)); /* Scan for {} */
gr_throw(&bline);
new->t_prog= gr_final(&vline);
clr_noscan(new->t_prog);
} 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,PROP)==0 ) {
for ( ptr=bol ; *ptr ; ptr++ ) {
switch( *ptr ) {
case C_IN: new->t_stdin= YES ; break ;
case C_OUT: new->t_stdout= YES ; break ;
case 'P': new->t_isprep= YES ; break ;
case 'p': new->t_prep= YES ; break ;
case 'm': new->t_prep= MAYBE ; break ;
case 'O': new->t_optim= YES ; break ;
case 'C': new->t_combine= YES ; break ;
default :
error("Unkown option %c in %s for %s",
*ptr,new->t_name,inname) ;
break ;
}
}
} 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,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="" ;
#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_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
l_add(&tr_list,(char *)new) ;
}
/************************** IO from core or file *******************/
static int incore ;
static growstring rline ;
static FILE *infile ;
static char *inptr ;
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 ;
#ifdef NEW
gr_cat(&rline,EM_DIR) ;
gr_cat(&rline,"/lib/n_ack/") ;
#else
gr_cat(&rline,ACK_DIR); gr_cat(&rline,"/") ;
#endif
gr_cat(&rline,name) ;
infile= fopen(gr_start(rline),"r") ;
#ifdef NEW
if ( !infile ) {
/* Try to read EM_DIR/lib/MACH/plan */
gr_throw(&rline) ;
gr_cat(&rline,EM_DIR) ;
gr_cat(&rline,"/lib/") ; gr_cat(&rline,name) ;
gr_cat(&rline,"/plan") ;
infile= fopen(gr_start(rline),"r") ;
}
#endif
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() {
if ( incore ) {
if ( *inptr==0 ) return EOF ;
return *inptr++ ;
}
return getc(infile) ;
}
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,154 +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"
#include "list.h"
#include "trans.h"
#include "data.h"
#include <signal.h>
#define ARG_MORE 40 /* The size of args chunks to allocate */
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 do_run() {
fatal("-g flag not implemeted") ;
/*NOTREACHED*/
return 0 ;
}
int runphase(phase) register trf *phase ; {
register list_elem *elem ;
if ( v_flag || debug ) {
if ( v_flag==1 && !debug ) {
vprint("%s",phase->t_name) ;
if ( !phase->t_combine ) {
vprint(" %s%s\n",p_basename,
rindex(in.p_path,SUFCHAR) ) ;
} else {
scanlist(l_first(c_arguments), elem) {
vprint(" %s",l_content(*elem)) ;
}
vprint("\n") ;
}
} else {
/* list all args */
vprint("%s",phase->t_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 ) ;
return run_exec(phase) ;
}
int run_exec(phase) trf *phase ; {
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 ) 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",
phase->t_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 open %s",out.p_path) ;
exit(1) ;
}
}
execv(phase->t_prog,arglist) ;
if ( phase->t_stdout ) { close(1) ; dup(2) ; }
error("Cannot execute %s",phase->t_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,244 +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"
#include "list.h"
#include "trans.h"
#include "data.h"
enum f_path setpath() { /* Try to find a transformation path */
start_scan();
/*
The end result is the setting of the t_do flags
in the transformation list.
The list is scanned for possible transformations
stopping at stopsuffix or a combine transformation.
The scan flags are set by this process.
When a transformation is found, it is compared with
the last transformation found, if better (or the first)
the scan bits are copied to the t_do bits, except for
the combiner which is remembered in a global pointer.
At the end of all transformations for all files, the combiner
is called, unless errors occurred.
*/
try(l_first(tr_list),p_suffix);
return scan_end();
}
/******************** data used only while scanning *******************/
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 com_err; /* Complain only once about multiple linkers*/
static trf *final; /* The last non-combining transformation */
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_do=NO ; t_cont(*scan)->t_scan=NO ;
t_cont(*scan)->t_keep=NO ;
}
final= (trf *)0 ;
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 the 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 ;
}
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_combine ) {
if ( stopsuffix ) {
trafo->t_scan=NO;
if ( *stopsuffix ) return ;
} else {
if( combiner &&
combiner!=trafo && !com_err ){
com_err++ ;
werror("Multiple linkers present %s and %s",
trafo->t_name,combiner->t_name) ;
} else {
combiner=trafo;
}
}
scan_found() ;
} else {
try(l_next(*scan),trafo->t_out);
}
trafo->t_scan= NO ;
}
}
}
scan_found() {
register list_elem *scan;
int ncount, ocount ;
register trf *keepit ;
keepit= (trf *)0 ;
suf_found= 1;
#ifdef DEBUG
if ( debug>=3 ) vprint("Scan found\n") ;
#endif
/* Gather data used in comparison */
ncount=0; ocount=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_combine) ) {
keepit= t_cont(*scan) ;
}
}
}
#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 - new n:%d, o:%d\n",
last_ncount,last_ocount,ncount,ocount) ;
}
#endif
if ( last_ncount== -1 || /* None found yet */
last_ncount>ncount || /* Shorter nec. path */
(last_ncount==ncount && /* Same nec. path, optimize?*/
(Optflag? 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_do=t_cont(*scan)->t_scan;
}
last_ncount=ncount; last_ocount=ocount;
if ( keepit ) final=keepit ;
}
}
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=index(f_char+1,SUFCHAR);
if ( l_char ? strncmp(f_char,suffix,l_char-f_char)==0 :
strcmp(f_char,suffix)==0 ) {
return 1 ;
}
}
return 0 ;
}
enum f_path scan_end() { /* Finalization */
/* Return value indicating whether a transformation was found */
/* Set the flags for the transformation up to, but not including,
the combiner
*/
#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
if ( cpp_trafo && stopsuffix &&
strcmp(stopsuffix,cpp_trafo->t_out)==0 ) {
final= cpp_trafo ;
}
/* There might not be a final when the file can be eaten
by the combiner
*/
if ( final ) final->t_keep=YES ;
if ( combiner ) {
if ( !combiner->t_do ) error("Combiner YES/NO");
combiner->t_do=NO ;
}
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,125 +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"
/* 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,672 +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"
#include "list.h"
#include "trans.h"
#include "grows.h"
#include "data.h"
/****************************************************************************/
/* 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) ) return 0 ;
if ( !phase->t_visited ) {
/* The flags are set up once.
At the first time the phase is used.
The program name and flags may already be touched
by vieuwargs.
*/
phase->t_visited=YES ;
if ( !rts && phase->t_rts ) rts= phase->t_rts ;
if ( phase->t_needed ) {
add_head(phase->t_needed) ;
add_tail(phase->t_needed) ;
}
}
getcallargs(phase) ;
ok= runphase(phase) ;
if ( !ok ) rmtemps() ;
/* Free the space occupied by the arguments,
except for the combiner, since we are bound to exit soon
and do not foresee further need of memory space */
if ( !phase->t_combine ) discardargs(phase) ;
disc_files() ;
return ok ;
}
int do_combine() {
setsvar(keeps(RTS), keeps(rts? rts : "") ) ;
if ( !outfile ) outfile= combiner->t_out ;
getmapflags(combiner);
return transform(combiner) ;
}
getmapflags(phase) register trf *phase ; {
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_combine ) {
scanlist(l_first(c_arguments),elem) {
if ( mapflag(&(phase->t_mapf),l_content(*elem)) ) {
throws(l_content(*elem)) ;
ptr= keeps(getvar(LIBVAR)) ;
clr_noscan(ptr) ;
l_content(*elem)= ptr ;
}
}
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)) ;
}
}
}
}
do_Rflag(argp) char *argp ; {
l_add(&R_list,argp) ;
}
char *needvar() {
static growstring needed ;
static int been_here = NO ;
if ( !been_here ) {
gr_init(&needed) ;
been_here=YES ;
gr_cat(&needed,headvar()) ;
gr_cat(&needed,tailvar()) ;
}
return gr_start(needed) ;
}
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(R_list), elem) {
set_Rflag(l_content(*elem)) ;
}
l_clear(&R_list) ;
scanlist(l_first(tr_list), elem) {
phase = t_cont(*elem) ;
if ( !phase->t_combine ) getmapflags(phase);
}
setpvar(keeps(NEEDS),needvar) ;
setpvar(keeps(HEAD),headvar) ;
setpvar(keeps(TAIL),tailvar) ;
}
set_Rflag(argp) register char *argp ; {
int seen ;
register char *eos ;
register list_elem *prog ;
register int length ;
char *eq ;
eos= index(&argp[2],'-');
eq= index(&argp[2],EQUAL) ;
if ( !eos ) {
eos= eq ;
} else {
if ( eq && eq<eos ) eos= eq ;
}
if ( !eos ) fuerror("Incorrect use of -R flag") ;
length= eos - &argp[2] ;
seen=NO ;
scanlist(l_first(tr_list), prog) {
if ( strncmp(t_cont(*prog)->t_name, &argp[2], length )==0 ) {
if ( *eos=='-' ) {
l_add(&(t_cont(*prog)->t_flags),eos) ;
} else {
t_cont(*prog)->t_prog= eos+1 ;
}
seen=YES ;
}
}
if ( !seen ) error("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=index(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= index(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) ;
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 ;
addargs(string) char *string ; {
register char *temp, *repc ;
register list_elem *elem ;
repc=index(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(c_arguments), elem ) {
l_add(curargs,l_content(*elem)) ;
}
}
return ;
}
if ( in.p_path ) { /* Not for the combiner */
temp=c_rep(string,repc,in.p_path) ;
addargs(temp) ;
throws(temp) ;
} else { /* For the combiner */
scanlist( l_first(c_arguments), elem ) {
temp=c_rep(string,repc,l_content(*elem)) ;
addargs(temp) ;
throws(temp) ;
}
}
return ;
}
repc=index(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 ;
unravel( gr_start(arg2), addargs ) ;
gr_throw(&arg2) ;
}
discardargs(phase) register trf *phase ; {
l_throw(&phase->t_args) ;
}

View File

@@ -1,30 +0,0 @@
/* 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' or 'name' */
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_optim:1 ; /* Is optimizer */
int t_isprep:1 ; /* Is preprocessor */
int t_keep:1 ; /* Keep the output file */
char *t_prog ; /* Pathname for load file */
list_head t_flags ; /* List of flags */
list_head t_args ; /* List of arguments */
int t_scan:1 ; /* Used while finding path's */
int t_do:1 ; /* Is in path to execute */
} ;
#define t_cont(elem) ((trf *)l_content(elem))

View File

@@ -1,190 +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
*
*/
/**********************************************************************/
/* */
/* Several utility routines used throughout ack */
/* error handling, string handling and such. */
/* */
/**********************************************************************/
#include "ack.h"
#include <ctype.h>
#include <stdio.h>
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[20] ;
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) ;
}
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,80 +0,0 @@
d=../..
l=$d/lib
h=$d/h
ASS_PATH=$l/em_ass
SEP_OPT=-i
CFLAGS=-O
all: ass$(SEP_OPT)
clean:
-rm -f ass-i ass-n *.o maktab *.old asstb.c
install : all
cp ass$(SEP_OPT) $(ASS_PATH)
cmp : all
cmp ass$(SEP_OPT) $(ASS_PATH)
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-n: 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 -n $(CFLAGS) -o ass-n \
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
ass-i: 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 -i $(CFLAGS) -o ass-i \
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 ip_spec.t
maktab 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 ; pr -3 ip_spec.t)

View File

@@ -1,384 +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;
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 '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,537 +0,0 @@
#include "ass00.h"
#include "assex.h"
/*
* (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
*
*/
/*
** Main routine of EM1-assembler/loader
*/
main(argc, argv)
int argc;
char **argv;
{
/*
* Usage: ass [-[d][p][m][u]] [-s(s/m/l)] [ [file] [flag] ] ...
* The d flag can be repeated several times, resulting in more
* debugging information.
*/
#ifdef EM_WSIZE
char workspace[2000] ;
#else
char workspace[6000] ;
#endif
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 size_t *p;
size_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)
*/
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;
}
}
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")) == NULL) {
error("can't open %s",arg);
return;
}
inpoff = 2;
if ((w = getu16()) == sp_magic )
read_compact();
else if (w == ARMAG) {
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 '-':
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; lbp!= lbp_cast 0; lbp= lbp_next ) {
lbp_next= lbp->l_chain;
freearea((area_t)lbp,(unsigned)sizeof *lbp) ;
}
}
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] == 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] == 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 JOHAN
if ( jflag ) return ;
#endif
#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[0] && (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[0] && (g->g_status&DEF)==0)
printf(" %s\n",glostring(g));
}
}
ertrap() { /* trap routine to drain input in case of compile errors */
if (fileno(ifile)== 0)
while (fgetc(ifile) != EOF)
;
exit(1);
}

View File

@@ -1,246 +0,0 @@
#include <stdio.h>
#include "../../h/em_spec.h"
#include "../../h/as_spec.h"
#include "../../h/em_flag.h"
#include "../../h/arch.h"
#include "../../h/local.h"
/*
* 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 size_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 IDLENGTH 8 /* length of glo's and pro's */
#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)
/* 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)[]; /* 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 */
} ;
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 */
};
/* 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[IDLENGTH+1]; /* name + null-byte */
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 3 /* 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[IDLENGTH+1]; /* name + 1 null-byte */
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,371 +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 "ass00.h"
#include "assex.h"
#include "ip_spec.h"
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 OP16 :
if ( i_flag==PAR_G ) return val>=0 && val<=maxadr ;
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 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 ;
char 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,55 +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 "ass00.h"
#include "assex.h"
/*
** 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,190 +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 "ass00.h"
#include "assex.h"
#include "ip_spec.h"
/*
** 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 %D\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:
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,211 +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 "ass00.h"
#include "assex.h"
#include "ip_spec.h"
#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; char typ; {
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 %D\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%14D",
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] != 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[0]) {
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[0]) {
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%10D %10s ",rl->r_off,r_data[rl->r_typ]);
switch(rl->r_typ) {
case RELADR:
case RELHEAD:
printf("%10D\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%10D %10s ",
rl->r_off,pflags(opchoice[rl->r_typ&~RELMNS])) ;
if ( rl->r_typ&RELMNS )
printf("%10D\n",rl->r_val.rel_i) ;
else printf("\n") ;
}
}
}
}
#endif

View File

@@ -1,341 +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 "ass00.h"
#include "assex.h"
/*
** 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) + 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] != 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] == 0) {
/*
* This symbol is shining new.
* Enter it in table except for status = SEARCHING
*/
if (status == SEARCHING)
return(0);
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)
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[0]) {
p->p_status |= OCC;
return(p);
}
p = searchproc(name,xprocs,oursize->n_xproc);
if (p->p_name[0]) {
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[0] && (p->p_status&EXT) )
error("pro '%s' conflicting use",name);
p = searchproc(name,mprocs,oursize->n_mproc);
if (p->p_name[0])
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[0])
error("pro '%s' exists already localy",name);
p = searchproc(name,xprocs,oursize->n_xproc);
if (p->p_name[0]) {
/*
* 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[0] && (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[0]) {
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] != 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;
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,412 +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 "ass00.h"
#include "assex.h"
#include "../../h/em_path.h"
/*
* 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 ;
rewind(f);
tmp=fdopen(dup(fileno(f)),"r");
fclose(f);
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 ;
shift=0 ; val=0 ;
while ( l-- ) {
val += ((cons_t)ctrunc(xgetc(f)))<<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 ;
}
#define MAXBYTE 255
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:
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 ;
default:
fatal("Unknown mode in setmode") ;
}
}
#ifndef CPM
int tmpfil() {
register char *fname, *cpname ;
char *sfname;
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.
*/
sfname = fname = "tmp.00000";
count = 10;
pid = getpid();
fname += 4;
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,861 +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 "ass00.h"
#include "assex.h"
#include "../../h/em_mes.h"
#include "../../h/em_pseu.h"
#include "../../h/em_ptyp.h"
/*
* 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 ans 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();
string[IDLENGTH] = '\0';
}
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[0]) {
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 */
case sp_cst2:
return wordsize ;
case sp_ilb1:
case sp_dnam:
case sp_doff:
case sp_pnam:
return ptrsize ;
case sp_scon:
/* Pad the string with zeros up to the wordsize */
while ( strlngth%wordsize ) {
if ( strlngth>=MAXSTRING )
fatal("string too long") ;
string[strlngth]=0 ;
strlngth++ ;
}
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 ) {
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!=1 ) {
werror("mes ms_ext must be first 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 ;
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");
putval();
amount= n/objsize ;
if ( amount>1 ) {
setmode(DATA_REP);
extadr(amount-1) ;
}
databytes +=n ;
getarg(sp_cst2);
if ( argval<0 || argval>1 ) error("illegal last argument") ;
}
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,137 +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
*
*/
/* 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"
#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() ;
#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 (short) ;
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 ;
#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 && l_ptr<=ptr )
fatal("Double freed") ;
if ( ((char *)ptr)+size > (char *)c_ptr && ptr<=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,125 +0,0 @@
#include "ass00.h"
#include "assex.h"
/*
* 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 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;
size_t sizes[NDEFAULT] = {
/* mlab, glab,mproc,xproc, proc */
{ 151, 29, 31, 73, 130 },
{ 307, 127, 151, 401, 460 },
{ 601, 251, 151, 401, 600 }
};
size_t *oursize = &sizes[1] ; /* point to selected sizes */

View File

@@ -1,158 +0,0 @@
/*
* global data
*/
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 size_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 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 size_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,298 +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 "ass00.h"
#include "assex.h"
#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")) == NULL )
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,68 +0,0 @@
.\" $Header$
.TH EM_ASS VI
.ad
.SH NAME
em_ass \- EM assembler/loader
.SH SYNOPSIS
/usr/em/lib/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"
Indicate that your program is small, medium or large.
Medium 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.
.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(I). 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(I) is provided with the -LIB flag it tells the
EM-optimizer \fIem_opt\fP(VI) to insert a library messages
when optimizing modules.
The EM-archiver \fIarch\fP(I) 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(I), arch(I)
.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 -sl flag,
the former means your 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,33 +0,0 @@
/* Contents of flags used when describing interpreter opcodes */
#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 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,475 +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 "ip_spec.h"
#include <stdio.h>
#include "../../h/em_spec.h"
#include "../../h/em_flag.h"
/* 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();
}
return 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 '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 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 ; 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 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 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,30 +0,0 @@
# $Header$
PREFLAGS=-I../../h
CFLAGS=$(PREFLAGS)
LDFLAGS=-i
LINTOPTS=-hbxac $(PREFLAGS)
LIBS=../../lib/em_data.a
# LEXLIB is system dependent, try -ll or -lln first
LEXLIB=-lln
cgg: bootgram.o
cc $(LDFLAGS) bootgram.o $(LIBS) $(LEXLIB) -o cgg
bootgram.c: bootgram.y
@echo expect 1 shift/reduce conflict
yacc bootgram.y
mv y.tab.c bootgram.c
install: cgg
cp cgg ../../lib/cgg
cmp: cgg
cmp cgg ../../lib/cgg
lint: bootgram.c
lint $(LINTOPTS) bootgram.c
clean:
rm -f bootgram.o bootgram.c bootlex.c cgg
bootgram.o: bootlex.c
bootgram.o: ../../h/cg_pattern.h

File diff suppressed because it is too large Load Diff

View File

@@ -1,190 +0,0 @@
%{
#ifndef NORCSID
static char rcsid2[]="$Header$";
#endif
/*
* (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
*
* Author: Hans van Staveren
*/
#undef input
#undef output
#undef unput
#define MAXBACKUP 50
%}
%%
"/*" { char c;
c = input();
do {
while (c!='*')
c = input();
c = input();
} while (c!='/');
}
"REGISTERS:" return(REGISTERHEAD);
"TOKENS:" return(TOKENHEAD);
"TOKENEXPRESSIONS:" return(EXPRESSIONHEAD);
"CODE:" return(CODEHEAD);
"MOVES:" return(MOVEHEAD);
"TESTS:" return(TESTHEAD);
"STACKS:" return(STACKHEAD);
"SIZEFACTOR" return(SIZEFAC);
"TIMEFACTOR" return(TIMEFAC);
"FORMAT" return(FORMAT);
"cost" return(COST);
"remove" return(REMOVE);
"|" return(SEP);
"samesign" return(SAMESIGN);
"inreg" return(INREG);
"sfit" return(SFIT);
"ufit" return(UFIT);
"defined" return(DEFINED);
"rom" return(ROM);
"loww" return(LOWW);
"highw" return(HIGHW);
"move" return(MOVE);
"erase" return(ERASE);
"allocate" return(ALLOCATE);
"tostring" return(TOSTRING);
"nocc" return(NOCC);
"setcc" return(SETCC);
"samecc" return(SAMECC);
"test" return(TEST);
"STACK" return(STACK);
"nocoercions" return(NOCOERC);
"&&" return(AND2);
"||" return(OR2);
"==" return(CMPEQ);
"!=" return(CMPNE);
"<=" return(CMPLE);
"<" return(CMPLT);
">" return(CMPGT);
">=" return(CMPGE);
">>" return(RSHIFT);
"<<" return(LSHIFT);
"!" return(NOT);
"~" return(COMP);
"..." return(ELLIPS);
EM_WSIZE { yylval.yy_intp = &wsize; return(CIDENT); }
EM_PSIZE { yylval.yy_intp = &psize; return(CIDENT); }
EM_BSIZE { yylval.yy_intp = &bsize; return(CIDENT); }
REGISTER { yylval.yy_string = "REGISTER"; return(TYPENAME); }
INT { yylval.yy_string = "INT"; return(TYPENAME); }
STRING { yylval.yy_string = "STRING"; return(TYPENAME); }
regvar return(REGVAR);
loop return(LOOP);
pointer return(POINTER);
float return(FLOAT);
return return(RETURN);
[_A-Za-z][_A-Za-z0-9]+ {register ident_p ip;
if(!lookident || (ip=ilookup(yytext,JUSTLOOKING))==0) {
yylval.yy_string = scopy(yytext);return(IDENT);
} else {
yylval.yy_ident = ip;
switch(ip->i_type) {
default:assert(0);
case IREG:return(RIDENT);
case IPRP:return(PIDENT);
case ITOK:return(TIDENT);
case IEXP:return(EIDENT);
}
}
}
[a-z] {yylval.yy_char = yytext[0]; return(LCASELETTER);}
[0-9]* {yylval.yy_int = atoi(yytext);return(NUMBER);}
(\"|"%)") { char *p; int c,tipe;
p=yytext;
for (;;) {
c = input();
switch(c) {
default: *p++=c;break;
case '\\':
*p++=c; *p++=input(); break;
case '\n':
yyerror("Unterminated string");
break;
case '"':
tipe=STRING; goto endstr;
case '%':
c=input();
if (c == '(') {
tipe=LSTRING;goto endstr;
} else {
*p++ = '%'; unput(c); break;
}
}
}
endstr:
*p++ = 0;
yylval.yy_string = scopy(yytext);
return(tipe);
}
^\#.*$ |
[ \t]* |
\n ;
. return(yytext[0]);
%%
char linebuf[256];
char prevbuf[256];
int linep;
int linepos; /* corrected for tabs */
char charstack[MAXBACKUP];
int nbackup=0;
output(c) {
assert(0);
}
input() {
if(nbackup)
return(charstack[--nbackup]);
if(linebuf[linep]==0) {
strcpy(prevbuf,linebuf);
if(fgets(linebuf,256,stdin)==NULL)
return(0);
lino++;
linepos=linep=0;
}
if (linebuf[linep] == '\t')
linepos = (linepos+8) & ~07;
else linepos++;
return(linebuf[linep++]);
}
unput(c) {
chktabsiz(nbackup,MAXBACKUP,"Lexical backup table");
charstack[nbackup++] = c;
}
yyerror(s,a1,a2,a3,a4) string s; {
fprintf(stderr,"%d\t%s%d\t%s\t%*c ",lino-1,prevbuf,lino,linebuf,
linepos-1,'^');
fprintf(stderr,s,a1,a2,a3,a4);
fprintf(stderr,"\n");
nerrors++;
}

View File

@@ -1,184 +0,0 @@
.TH
.I cpp
.SH NAME
cpp \- C Pre-Processor
.SH SYNOPSIS
cpp [\-options] files
.SH DESCRIPTION
.I Cpp
reads one or more files, expands macros and include
files, and writes an input file for the C compiler.
All output is to cpp.tmp (cpp.tmp.c on Unix).
.br
The following options are supported. On non-Unix systems,
options may be given in either case.
.IP -Ofile
Output to this file, instead of the default.
.IP -S
Output to stdout, instead of the default.
.IP -Idirectory
Add this directory to the list of
directories searched for #include "..." and #include <...>
commands. Note that there is no space between the
"-I" and the directory string. More than one -I command
is permitted.
.IP -L
.I Cpp
transmits line number information to
the C compiler by outputting "#line <number>" records.
If the -L option is given, this record will be transmitted
as "#", allowing the output of
.I cpp
to be input to a compiler
without an intervening preprocessor without error.
.IP -Dname=value
Define the name as if the programmer wrote
.br
.nf
#define name value
.fi
.br
at the start of the first file. If "=value" is not
given, a value of "1" will be used.
.br
On non-unix systems, all alphabetic text will be forced
to upper-case.
.br
.IP -Uname
Undefine the name as if
.br
.nf
#undef name
.fi
.br
were given. On non-Unix systems, "name" will be forced to
upper-case.
The following names are always available unless undefined:
.RS
.IP __FILE__
The input (or #include) file being compiled
(as a quoted string).
.IP __LINE__
The line number being compiled.
.IP __DATE__
The date and time of compilation as
a Unix ctime quoted string (the trailing newline is removed).
.RE
Thus,
.br
.nf
printf("Bug at line %s,", __LINE__);
printf(" source file %s", __FILE__);
printf(" compiled on %s", __DATE__);
.fi
.IP
-Xnumber
Enable debugging code. If no value is
given, a value of 1 will be used. (For maintenence of
.I cpp
only.)
.SH "COMMENTS IN MACRO TEXT AND ARGUMENT CONCATENATION"
.br
Comments are removed from the input text. The comment
characters serve as an invisible token delimiter. Thus,
the macro
.nf
#define CAT(a, b) b/**/a
int value = CAT(1, 2);
.fi
Will generate "int value = 21;".
.br
A better way of concatenating arguments is as follows:
.nf
#define I(x)x
#define CAT(x,y)I(x)y
int value = CAT(1, 2);
.fi
If the above macros are defined without extraneous
spaces, they will be transportable to other implementations.
.br
.SH DIFFERENCES
.br
The following is a list of differences between this
pre-processor and the Unix V7 preprocessor which was
written by John Reiser. It is probably not complete.
.IP o
Macro formal parameters are recognized within
quoted strings and character constants in macro definitions.
For example,
.nf
#define foo(a) "Today is a"
printf(foo(tuesday));
.fi
Would print "Today is tuesday".
.br
Recognition of formal parameters in macro replacement
strings is not permitted by the Draft ANSI C Standard.
It is permitted in this implementation if cpp was
compiled with the STRING_FORMAL parameter set appropriately.
.br
Unlike Reiser's implementation, the '\e' "quote next character"
does just that. I.e.
.nf
#define foo(a) "Today is \ea a"
printf(foo(tuesday));
.fi
Would print "Today is a tuesday". Note that this may
not be portable.
.IP o
Reiser's implementation removes "escaped" linefeeds
(The two character sequence \e<LF>) within macros. This
implementation preserves them. For example, a macro which
generates control commands might be written
.nf
#define foo(a, b) \e
#define a b \e
.fi
.nf
foo(fubar, foobar)
int fubar;
.fi
The above would generate "int foobar;" and a warning message.
Reiser's scan is slightly different.
.SH "ANSI C STANDARD"
.I Cpp
implements most of the ANSI draft standard.
You should be aware of the following:
.IP o
In the draft standard, the \en (backslash-newline)
character is "invisible" to all processing. In this implementation,
it is invisible to strings, but acts a "whitespace" (token-delimiter)
outside of strings. This considerably simplifies error
message handling.
.IP o
The following extensions to C are processed by cpp:
.nf
.sp 1
.ta 4 27
#elif expression (#else #if)
'\exNNN' (Hexadecimal constants)
'\ea' (Ascii BELL)
'\ev' (Ascii VT)
#if defined NAME (1 if defined, 0 if not)
#if defined (NAME) (1 if defined, 0 if not)
unary + (gag me with a spoon)
.fi
.IP o
The draft standard has extended C, adding a string
concatenation operator, where
.br
.nf
"foo" "bar"
.fi
.br
is regarded as the single string "foobar". It is not clear
from the draft standard whether this applies to pre-processing
if macro formals are recognized in strings.
.SH "ERROR MESSAGES"
.br
Many.
.br
.SH AUTHOR
.br
Martin Minow
.br

View File

@@ -1,38 +0,0 @@
# $Header$
d=../..
h=$d/h
l=$d/lib
DEC_PATH=decode
ENC_PATH=encode
DATA_PATH=$l/em_data.a
CFLAGS=-O -I$h
all: $(DEC_PATH) $(ENC_PATH)
$(DEC_PATH): decode.o $(DATA_PATH)
cc -n -o $(DEC_PATH) decode.o $(DATA_PATH)
$(ENC_PATH): encode.o $(DATA_PATH)
cc -n -o $(ENC_PATH) encode.o $(DATA_PATH)
encode.o: $h/em_spec.h $h/em_pseu.h $h/em_flag.h $h/em_ptyp.h $h/em_mes.h
decode.o: $h/em_spec.h $h/em_pseu.h $h/em_flag.h $h/em_ptyp.h $h/em_mes.h
clean:
rm -f $(DEC_PATH) $(ENC_PATH) *.o *.old
install : all
cp $(DEC_PATH) $l/em_$(DEC_PATH)
cp $(ENC_PATH) $l/em_$(ENC_PATH)
cmp : all
cmp $(DEC_PATH) $l/$(DEC_PATH)
cmp $(ENC_PATH) $l/$(ENC_PATH)
opr:
make pr ^ opr
pr:
@pr -n Makefile decode.c encode.c

View File

@@ -1,499 +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
*
*/
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
/*
* Decode compact EM assembly language
*
* Author: Johan Stevenson, Vrije Universiteit, Amsterdam
*/
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <em_spec.h>
#include <em_pseu.h>
#include <em_flag.h>
#include <em_ptyp.h>
#include <em_mes.h>
#define get8() ((unsigned)getchar())
#define check(x) if (!(x)) fail_check()
#define MAXSTR 256
/*
* global variables
*/
int opcode;
int offtyp;
long argval;
int dlbval;
char string[MAXSTR];
int strsiz;
int wsize;
int psize;
int lineno;
int argnum;
int errors;
char *progname;
char *filename;
long wordmask[] = { /* allowed bits in a word */
0x00000000,
0x000000FF,
0x0000FFFF,
0x00000000,
0xFFFFFFFF
};
long sizemask[] = { /* allowed bits in multiples of 'wsize' */
0x00000000,
0x7FFFFFFF,
0x7FFFFFFE,
0x00000000,
0x7FFFFFFC
};
/*
* external tables
*/
extern char em_flag[];
extern short em_ptyp[];
extern char em_mnem[][4];
extern char em_pseu[][4];
/*
* routines
*/
int get16();
long get32();
main(argc,argv) char **argv; {
progname = argv[0];
if (argc >= 2) {
filename = argv[1];
if (freopen(argv[1],"r",stdin) == NULL)
fatal("can't open %s",argv[1]);
}
if (argc >= 3)
if (freopen(argv[2],"w",stdout) == NULL)
fatal("can't create %s",argv[2]);
if (get16() != sp_magic)
fatal("bad magic word");
/* In System III the array is called _ctype[] without the trailing '_' */
(_ctype_+1)['_'] = (_ctype_+1)['a'];
while (nextline())
;
return(errors ? -1 : 0);
}
/* ----- copy ----- */
int nextline() {
register t;
lineno++;
argnum = 1;
switch (t = table1()) {
case EOF:
return(0);
case sp_fmnem:
instr();
break;
case sp_fpseu:
pseudo();
break;
case sp_ilb1:
case sp_ilb2:
argnum = 0;
putarg(sp_cst2);
break;
case sp_dlb1:
case sp_dlb2:
case sp_dnam:
argnum = 0;
putarg(t);
break;
default:
error("unknown opcode %d",t);
}
putchar('\n');
return(1);
}
instr() {
register i,j,t;
register long l;
i = opcode - sp_fmnem;
printf(" %s",em_mnem[i]);
j = em_flag[i] & EM_PAR;
if (j == PAR_NO)
return;
t = em_ptyp[j];
t = getarg(t);
/*
* range checking
*/
switch (j) {
case PAR_N:
check(argval >= 0);
break;
case PAR_G:
if (t != sp_cst2 && t != sp_cst4)
break;
check(argval >= 0);
/* fall through */
case PAR_L:
l = argval >= 0 ? argval : -argval;
check((l & ~wordmask[psize]) == 0);
break;
case PAR_W:
if (t == sp_cend)
break;
check((argval & ~wordmask[wsize]) == 0);
/* fall through */
case PAR_S:
check(argval != 0);
/* fall through */
case PAR_Z:
check((argval & ~sizemask[wsize]) == 0);
break;
case PAR_O:
check(argval != 0);
check((argval & ~sizemask[wsize])==0 || (wsize % argval)==0);
break;
case PAR_B:
t = sp_ilb2;
break;
case PAR_R:
check(argval >= 0 && argval <= 2);
break;
}
putarg(t);
}
pseudo() {
register i,t;
i = opcode;
printf(" %s",em_pseu[i - sp_fpseu]);
switch (i) {
case ps_bss:
case ps_hol:
putarg(getarg(cst_ptyp));
putarg(getarg(val_ptyp));
putarg(getarg(ptyp(sp_cst2)));
check(argval==0 || argval==1);
break;
case ps_rom:
case ps_con:
putarg(getarg(val_ptyp));
while ((t = getarg(any_ptyp)) != sp_cend)
putarg(t);
break;
case ps_mes:
putarg(getarg(ptyp(sp_cst2)));
if (argval == ms_emx) {
putarg(getarg(ptyp(sp_cst2)));
check(argval > 0 && argval <= 4);
wsize = (int) argval;
putarg(getarg(ptyp(sp_cst2)));
check(argval > 0 && argval <= 4);
psize = (int) argval;
}
while ((t = getarg(any_ptyp)) != sp_cend)
putarg(t);
break;
case ps_exa:
case ps_ina:
putarg(getarg(sym_ptyp));
break;
case ps_exp:
case ps_inp:
putarg(getarg(ptyp(sp_pnam)));
break;
case ps_exc:
putarg(getarg(ptyp(sp_cst2)));
putarg(getarg(ptyp(sp_cst2)));
break;
case ps_pro:
putarg(getarg(ptyp(sp_pnam)));
putarg(getarg(cst_ptyp|ptyp(sp_cend)));
break;
case ps_end:
putarg(getarg(cst_ptyp|ptyp(sp_cend)));
break;
default:
error("bad pseudo %d",i);
}
}
/* ----- input ----- */
int getarg(typset) {
register t,argtyp;
argtyp = t = table2();
if (t == EOF)
fatal("unexpected EOF");
t -= sp_fspec;
assert(t >= 0 && t < 16);
t = 1 << t;
if ((typset & t) == 0)
error("bad argument type %d",argtyp);
return(argtyp);
}
int table1() {
register i;
i = get8();
if (i < sp_fmnem+sp_nmnem && i >= sp_fmnem) {
opcode = i;
return(sp_fmnem);
}
if (i < sp_fpseu+sp_npseu && i >= sp_fpseu) {
opcode = i;
return(sp_fpseu);
}
if (i < sp_filb0+sp_nilb0 && i >= sp_filb0) {
argval = i - sp_filb0;
return(sp_ilb2);
}
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 table3(i) {
long consiz;
switch(i) {
case sp_ilb1:
argval = get8();
break;
case sp_dlb1:
dlbval = get8();
break;
case sp_dlb2:
dlbval = get16();
if ( dlbval<0 ) {
error("illegal data label .%d",dlbval);
dlbval=0 ;
}
break;
case sp_cst2:
argval = get16();
break;
case sp_ilb2:
argval = get16();
if ( argval<0 ) {
error("illegal instruction label %D",argval);
argval=0 ;
}
break;
case sp_cst4:
argval = get32();
break;
case sp_dnam:
case sp_pnam:
getstring(1);
break;
case sp_scon:
getstring(0);
break;
case sp_doff:
offtyp = getarg(sym_ptyp);
getarg(cst_ptyp);
break;
case sp_icon:
case sp_ucon:
case sp_fcon:
getarg(cst_ptyp);
consiz = (long) argval;
getstring(0);
argval = consiz;
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) ;
}
long get32() {
register long 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) ;
}
getstring(ident) {
register char *p;
register n;
getarg(cst_ptyp);
if (argval < 0 || argval > MAXSTR)
fatal("string/identifier too long");
strsiz = n = argval;
p = string;
while (--n >= 0)
*p++ = get8();
if (ident) {
if (!isascii(string[0]) || !isalpha(string[0])) {
identerror();
return;
}
for (n=strsiz,p=string+1;--n>0;p++)
if (!isascii(*p) || !isalnum(*p)) {
identerror();
return;
}
}
}
/* ----- output ----- */
putarg(t) {
if (argnum != 0)
putchar(argnum == 1 ? ' ' : ',');
argnum++;
puttyp(t);
}
puttyp(t) {
switch (t) {
case sp_ilb1:
case sp_ilb2:
printf("*%d",(int) argval);
break;
case sp_dlb1:
case sp_dlb2:
printf(".%d",dlbval);
break;
case sp_dnam:
putstr(0,0);
break;
case sp_cst2:
case sp_cst4:
printf("%D",argval);
break;
case sp_doff:
puttyp(offtyp);
if (argval >= 0) putchar('+');
printf("%D",argval);
break;
case sp_pnam:
putstr('$',0);
break;
case sp_scon:
putstr('\'','\'');
break;
case sp_icon:
putstr(0,'I');
printf("%D",argval);
break;
case sp_ucon:
putstr(0,'U');
printf("%D",argval);
break;
case sp_fcon:
putstr(0,'F');
printf("%D",argval);
break;
case sp_cend:
putchar('?');
break;
}
}
putstr(c,c2) register c; {
register char *p;
if (c)
putchar(c);
p = string;
while (--strsiz >= 0) {
c = *p++ & 0377;
if (c >= 040 && c < 0177) {
if (c == '\'' || c == '\\')
putchar('\\');
putchar(c);
} else
printf("\\%03o",c);
}
if (c2)
putchar(c2);
}
/* ----- error handling ----- */
fail_check() {
error("argument range error");
}
identerror() {
error("'%s' is not a correct identifier",string);
}
/* VARARGS */
error(s,a1,a2,a3,a4) char *s; {
fprintf(stderr,
"%s: line %d: ",
filename ? filename : progname,
lineno);
fprintf(stderr,s,a1,a2,a3,a4);
fprintf(stderr,"\n");
errors++;
}
/* VARARGS */
fatal(s,a1,a2,a3,a4) char *s; {
error(s,a1,a2,a3,a4);
exit(-1);
}

View File

@@ -1,40 +0,0 @@
.\" $Header$
.TH EM_DECODE VI
.ad
.SH NAME
em_decode,em_encode \- compact to readable EM and v.v.
.SH SYNOPSIS
/usr/em/lib/em_decode [ inputfile [ outputfile ] ]
.br
/usr/em/lib/em_encode [ inputfile [ outputfile ] ]
.SH DESCRIPTION
Most programs involved with the EM project only produce and accept
EM programs in compact form.
These files are only machine readable.
A description of this compact form can be found in [1].
To inspect the code produced by compilers or to patch them for one reason
or another, you need human readable assembly code.
Em_decode will do the job for you.
.PP
Em_decode accepts the normal compact form in both optimized and
unoptimized form
.PP
Sometimes you have to make some special routines directly
in EM, for instance the routines implementing the system calls.
At these times you may use em_encode to produce compact routines
out of these human readable assembly modules.
.PP
The first argument is the input file.
The second argument is the output file.
Both programs can act as a filter.
.SH "SEE ALSO"
.IP [1]
A.S.Tanenbaum, Ed Keizer, Hans van Staveren & J.W.Stevenson
"Description of a machine architecture for use of
block structured languages" Informatica rapport IR-81.
.IP [2]
ack(I)
.SH DIAGNOSTICS
Error messages are intended to be self-explanatory.
.SH AUTHOR
Johan Stevenson, Vrije Universiteit.

View File

@@ -1,761 +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
*
*/
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
/*
* Encode to compact EM assembly language
*
* Author: Johan Stevenson, Vrije Universiteit, Amsterdam
*/
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include <setjmp.h>
#include <em_spec.h>
#include <em_pseu.h>
#include <em_flag.h>
#include <em_ptyp.h>
#include <em_mes.h>
#define put8(x) putchar(x)
#define check(x) if (!(x)) fail_check()
#define fit16i(x) ((x) >= 0xFFFF8000 && (x) <= 0x00007FFF)
#define fit8u(x) ((x) >= 0 && (x) <= 0xFF)
#define MAXSTR 256
#define HSIZE 256
#define EMPTY (EOF-1)
/*
* global variables
*/
int opcode;
int offtyp;
long argval;
int dlbval;
char string[MAXSTR];
int strsiz;
int wsize;
int psize;
int lineno;
int argnum;
int errors;
char *progname;
char *filename = "INPUT";
long wordmask[] = { /* allowed bits in a word */
0x00000000,
0x000000FF,
0x0000FFFF,
0x00000000,
0xFFFFFFFF
};
long sizemask[] = { /* allowed bits in multiples of 'wsize' */
0x00000000,
0x7FFFFFFF,
0x7FFFFFFE,
0x00000000,
0x7FFFFFFC
};
int peekc = EMPTY;
int hashtab[HSIZE];
jmp_buf recover;
/*
* external tables
*/
extern char em_flag[];
extern short em_ptyp[];
extern char em_mnem[][4];
extern char em_pseu[][4];
int main(argc,argv) char **argv; {
progname = argv[0];
if (argc >= 2) {
filename = argv[1];
if (freopen(filename,"r",stdin) == NULL)
fatal("can't open %s",filename);
}
if (argc >= 3)
if (freopen(argv[2],"w",stdout) == NULL)
fatal("can't create %s",argv[2]);
init();
put16(sp_magic);
setjmp(recover);
while (nextline())
;
return(errors ? -1 : 0);
}
/* ----- copy ----- */
int nextline() {
register c,i;
lineno++;
argnum = 1;
c = nextchar();
if (c == EOF)
return(0);
if (isspace(c) && c != '\n') {
c = nospace();
if (isalpha(c)) {
inmnem(c);
if (opcode <= sp_lmnem)
instr();
else
pseudo();
} else
peekc = c;
} else if (c == '#') {
line_line();
} else {
peekc = c;
i = gettyp(sym_ptyp | ptyp(sp_cst2) | ptyp(sp_cend));
switch (i) {
case sp_cst2:
i = (int) argval;
if (i >= 0 && i < sp_nilb0)
put8(i + sp_filb0);
else
putarg(sp_ilb2);
break;
case sp_dlb2:
case sp_dnam:
putarg(i);
break;
case sp_cend:
break;
}
}
if (nospace() != '\n')
syntax("end of line expected");
return(1);
}
instr() {
register i,j,t;
register long l;
i = opcode;
put8(i);
i -= sp_fmnem;
j = em_flag[i] & EM_PAR;
if (j == PAR_NO)
return;
t = em_ptyp[j];
if (j == PAR_B)
t = ptyp(sp_ilb2);
t = getarg(t);
/*
* range checking
*/
switch (j) {
case PAR_N:
check(argval >= 0);
break;
case PAR_G:
if (t != sp_cst2 && t != sp_cst4)
break;
check(argval >= 0);
/* fall through */
case PAR_L:
l = argval >= 0 ? argval : -argval;
check((l & ~wordmask[psize]) == 0);
break;
case PAR_W:
if (t == sp_cend)
break;
check((argval & ~wordmask[wsize]) == 0);
/* fall through */
case PAR_S:
check(argval != 0);
/* fall through */
case PAR_Z:
check((argval & ~sizemask[wsize]) == 0);
break;
case PAR_O:
check(argval != 0);
check((argval & ~sizemask[wsize])==0 || (wsize % argval)==0);
break;
case PAR_B:
t = sp_cst2;
break;
case PAR_R:
check(argval >= 0 && argval <= 2);
break;
}
putarg(t);
}
pseudo() {
register i,t;
i = opcode;
put8(i);
switch (i) {
case ps_bss:
case ps_hol:
putarg(getarg(cst_ptyp));
putarg(getarg(val_ptyp));
putarg(getarg(ptyp(sp_cst2)));
check(argval==0 || argval==1);
break;
case ps_rom:
case ps_con:
putarg(getarg(val_ptyp));
do
putarg(t = getarg(any_ptyp));
while (t != sp_cend);
break;
case ps_mes:
putarg(getarg(ptyp(sp_cst2)));
if (argval == ms_emx) {
putarg(getarg(ptyp(sp_cst2)));
check(argval > 0 && argval <= 4);
wsize = (int) argval;
putarg(getarg(ptyp(sp_cst2)));
check(argval > 0 && argval <= 4);
psize = (int) argval;
}
do
putarg(t = getarg(any_ptyp));
while (t != sp_cend);
break;
case ps_exa:
case ps_ina:
putarg(getarg(sym_ptyp));
break;
case ps_exp:
case ps_inp:
putarg(getarg(ptyp(sp_pnam)));
break;
case ps_exc:
putarg(getarg(ptyp(sp_cst2)));
putarg(getarg(ptyp(sp_cst2)));
break;
case ps_pro:
putarg(getarg(ptyp(sp_pnam)));
putarg(getarg(cst_ptyp|ptyp(sp_cend)));
break;
case ps_end:
putarg(getarg(cst_ptyp|ptyp(sp_cend)));
break;
default:
syntax("bad pseudo %d",i);
}
}
/* ----- input ----- */
int getarg(typset) {
register c;
if (argnum != 1) {
c = nospace();
if (c != ',') {
if (c != '\n')
syntax("comma expected");
peekc = c;
}
}
argnum++;
return(gettyp(typset));
}
int gettyp(typset) {
register c,t,sp;
c = nospace();
if (c == '\n') {
peekc = c;
sp = sp_cend;
} else if (isdigit(c) || c == '+' || c == '-' || c == '(') {
sp = inexpr1(c);
if (sp == sp_cst4 && fit16i(argval))
sp = sp_cst2;
} else if (isalpha(c)) {
inname(c);
sp = offsetted(sp_dnam);
} else if (c == '.') {
in15u();
dlbval = (int) argval;
sp = offsetted(sp_dlb2);
} else if (c == '*') {
in15u();
sp = sp_ilb2;
} else if (c == '$') {
inname(nextchar());
sp = sp_pnam;
} else if (c == '"' || c == '\'') {
sp = instring(c);
} else if (c == '?') {
sp = sp_cend;
} else
syntax("operand expected");
t = sp - sp_fspec;
assert(t >= 0 && t < 16);
t = 1 << t;
if ((typset & t) == 0)
error("bad argument type %d",sp);
return(sp);
}
int offsetted(sp) {
register c;
c = nospace();
if (c == '+' || c == '-') {
gettyp(cst_ptyp);
if (c == '-')
argval = -argval;
offtyp = sp;
return(sp_doff);
}
peekc = c;
return(sp);
}
inname(c) register c; {
register char *p;
if (isalpha(c) == 0)
syntax("letter expected");
p = string;
do {
if (p < &string[MAXSTR-1])
*p++ = c;
c = nextchar();
} while (isalnum(c));
peekc = c;
*p = '\0';
strsiz = p - string;
}
int inmnem(c) register c; {
register unsigned h;
register i;
inname(c);
h = hash(string);
for (;;) {
h++;
h %= HSIZE;
i = hashtab[h];
if (i == 0)
syntax("bad mnemonic");
if (i <= sp_lmnem) {
assert(i >= sp_fmnem);
if (strcmp(string,em_mnem[i - sp_fmnem]) != 0)
continue;
return(opcode = i);
}
assert(i <= sp_lpseu && i >= sp_fpseu);
if (strcmp(string,em_pseu[i - sp_fpseu]) != 0)
continue;
return(opcode = i);
}
}
int inexpr1(c) register c; {
long left;
if ((c = inexpr2(c)) != sp_cst4)
return(c);
for (;;) {
c = nospace();
if (c != '+' && c != '-') {
peekc = c;
break;
}
left = argval;
if (inexpr2(nospace()) != sp_cst4)
syntax("term expected");
if (c == '+')
argval += left;
else
argval = left - argval;
}
return(sp_cst4);
}
int inexpr2(c) register c; {
long left;
if ((c = inexpr3(c)) != sp_cst4)
return(c);
for (;;) {
c = nospace();
if (c != '*' && c != '/' && c != '%') {
peekc = c;
break;
}
left = argval;
if (inexpr3(nospace()) != sp_cst4)
syntax("factor expected");
if (c == '*')
argval *= left;
else if (c == '/')
argval = left / argval;
else
argval = left % argval;
}
return(sp_cst4);
}
inexpr3(c) register c; {
if (c == '(') {
if (inexpr1(nospace()) != sp_cst4)
syntax("expression expected");
if (nospace() != ')')
syntax("')' expected");
return(sp_cst4);
}
return(innumber(c));
}
int innumber(c) register c; {
register char *p;
register n;
int expsign;
static char numstr[MAXSTR];
long atol();
p = numstr;
expsign = 0;
if (c == '+' || c == '-') {
if (c == '-')
*p++ = c;
c = nextchar();
}
if (isdigit(c) == 0)
syntax("digit expected");
n = sp_cst4;
for (;;) {
if (p >= &numstr[MAXSTR-1])
fatal("number too long");
*p++ = c;
c = nextchar();
if (c == '.' || c == 'e' || c == 'E') {
expsign = c != '.';
n = sp_fcon;
continue;
}
if (expsign) {
expsign = 0;
if (c == '+' || c == '-')
continue;
}
if (isdigit(c) == 0)
break;
}
peekc = c;
*p = '\0';
c = nospace();
if (n == sp_fcon && c != 'F')
syntax("'F' expected");
if (c == 'I' || c == 'U' || c == 'F')
return(incon(numstr,c));
peekc = c;
argval = atol(numstr);
return(sp_cst4);
}
in15u() {
if (innumber(nextchar()) != sp_cst4)
syntax("integer expected");
check((argval & ~077777) == 0);
}
int incon(p,c) register char *p; {
register char *q;
q = string;
while (*q++ = *p++)
;
strsiz = q - string - 1;
gettyp(cst_ptyp);
return(c == 'I' ? sp_icon : (c == 'U' ? sp_ucon : sp_fcon));
}
int instring(termc) {
register char *p;
register c;
p = string;
for (;;) {
c = nextchar();
if (c == '\n' || c == EOF) {
peekc = c;
syntax("non-terminated string");
}
if (c == termc) {
if (termc == '"')
*p++ = '\0';
break;
}
if (c == '\\')
c = inescape();
if (p >= &string[MAXSTR-1])
fatal("string too long");
*p++ = c;
}
strsiz = p - string;
return(sp_scon);
}
int inescape() {
register c,j,r;
c = nextchar();
if (c >= '0' && c <= '7') {
r = c - '0';
for (j = 0; j < 2; j++) {
c = nextchar();
if (c < '0' || c > '7') {
peekc = c;
return(r);
}
r <<= 3;
r += (c - '0');
}
return(r);
}
switch (c) {
case 'b': return('\b');
case 'f': return('\f');
case 'n': return('\n');
case 'r': return('\r');
case 't': return('\t');
}
return(c);
}
int nospace() {
register c;
do
c = nextchar();
while (isspace(c) && c != '\n');
if (c == ';')
do
c = nextchar();
while (c != '\n' && c != EOF);
return(c);
}
int nextchar() {
register c;
if (peekc != EMPTY) {
c = peekc;
peekc = EMPTY;
return(c);
}
c = getchar();
if (isascii(c) == 0 && c != EOF)
fatal("non-ascii char");
return(c);
}
line_line() {
register char *p,*q;
static char filebuff[MAXSTR+1];
gettyp(ptyp(sp_cst2));
lineno = (int) (argval-1);
gettyp(ptyp(sp_scon));
p = string;
q = filebuff;
while (--strsiz >= 0)
*q++ = *p++;
*q = '\0';
filename = filebuff;
}
init() {
register i;
for (i = sp_fmnem; i <= sp_lmnem; i++)
pre_hash(i,em_mnem[i - sp_fmnem]);
for (i = sp_fpseu; i <= sp_lpseu; i++)
pre_hash(i,em_pseu[i - sp_fpseu]);
/* treat '_' as letter */
/* In System III the array is called _ctype[] without the trailing '_' */
(_ctype_+1)['_'] = (_ctype_+1)['a'];
}
pre_hash(i,s) char *s; {
register unsigned h;
assert(i != 0);
h = hash(s);
for (;;) {
h++;
h %= HSIZE;
if (hashtab[h] == 0) {
hashtab[h] = i;
return;
}
}
}
int hash(s) register char *s; {
register h;
h = 0;
while (*s) {
h <<= 1;
h += *s++;
}
return(h);
}
/* ----- output ----- */
putarg(sp) register sp; {
register i;
switch (sp) {
case sp_ilb2:
i = (int) argval;
if (fit8u(i)) {
put8(sp_ilb1);
put8(i);
break;
}
put8(sp);
put16(i);
break;
case sp_dlb2:
i = dlbval;
if (fit8u(i)) {
put8(sp_dlb1);
put8(i);
break;
}
put8(sp);
put16(i);
break;
case sp_cst2:
case sp_cst4:
if (fit16i(argval) == 0) {
put8(sp_cst4);
put32(argval);
break;
}
i = (int) argval;
if (i >= -sp_zcst0 && i < sp_ncst0 - sp_zcst0) {
put8(i + sp_zcst0 + sp_fcst0);
break;
}
put8(sp_cst2);
put16(i);
break;
case sp_doff:
put8(sp);
putarg(offtyp);
putarg(sp_cst4);
break;
case sp_dnam:
case sp_pnam:
case sp_scon:
put8(sp);
putstr();
break;
case sp_icon:
case sp_ucon:
case sp_fcon:
put8(sp);
putarg(sp_cst4);
putstr();
break;
case sp_cend:
put8(sp);
break;
}
}
putstr() {
register char *p;
long consiz;
consiz = argval;
argval = strsiz;
putarg(sp_cst4);
argval = consiz;
p = string;
while (--strsiz >= 0)
put8(*p++);
}
put16(w) int w; {
put8(w);
put8(w >> 8);
}
put32(f) long f; {
put16((int) f);
put16((int)(f >> 16));
}
/* ----- error handling ----- */
fail_check() {
error("argument range error");
}
/* VARARGS */
error(s,a1,a2,a3,a4) char *s; {
fprintf(stderr,"%s: line %d: ", filename, lineno);
fprintf(stderr,s,a1,a2,a3,a4);
fprintf(stderr,"\n");
errors++;
}
/* VARARGS */
fatal(s,a1,a2,a3,a4) char *s; {
error(s,a1,a2,a3,a4);
exit(-1);
}
/* VARARGS */
syntax(s,a1,a2,a3,a4) char *s; {
register c;
error(s,a1,a2,a3,a4);
do
c = nextchar();
while (c != '\n' && c != EOF);
longjmp(recover);
}

View File

@@ -1,202 +0,0 @@
# $Header$
CFILES=main.c getline.c lookup.c var.c process.c backward.c util.c\
alloc.c putline.c cleanup.c peephole.c flow.c reg.c
OFILES=main.o getline.o lookup.o var.o process.o backward.o util.o\
alloc.o putline.o cleanup.o peephole.o flow.o reg.o
KFILES=main.k getline.k lookup.k var.k process.k backward.k util.k\
alloc.k putline.k cleanup.k peephole.k flow.k reg.k
LIBS=../../lib/em_data.a
CFLAGS=-O -DNDEBUG
LDFLAGS=-i
LINT=lint
OPR=wide|opr
XREF=xref -c -w80
PROPTS=
# LEXLIB is implementation dependent, try -ll or -lln first
LEXLIB=-ll
.DEFAULT:
co -q $<
opt: $(OFILES) pattern.o $(LIBS)
cc $(LDFLAGS) $(CFLAGS) $(OFILES) pattern.o $(LIBS) -o opt
test: opt testopt
testopt
cmp : opt
cmp opt ../../lib/em_opt
install:opt
size opt ../../lib/em_opt
cp opt ../../lib/em_opt
pattern.c: patterns mktab
/lib/cpp patterns | mktab > pattern.c
mktab: mktab.o $(LIBS)
cc $(CFLAGS) mktab.o $(LIBS) $(LEXLIB) -o mktab
depend: makedepend
makedepend
lint: $(CFILES) pattern.c
$(LINT) $(CFILES) pattern.c>lint 2>&1
printall:
-pr $(PROPTS) Makefile -n *.h `ls $(CFILES)` mktab.y scan.l patterns|$(OPR)
touch print
print: Makefile *.h $(CFILES) mktab.y scan.l patterns
-pr $(PROPTS) -n $? | $(OPR)
opr:
make pr ^ $(OPR)
pr:
@pr $(PROPTS) -n Makefile *.h $(CFILES) mktab.y scan.l patterns
xref:
$(XREF) *.h $(CFILES) | pr $(PROPTS) -h "XREF EMOPT"|$(OPR)&
sizes: opt
-nm opt | sort -n| /usr/plain/bin/map
clean:
rm -f *.o opt mktab mktab.c scan.c pattern.c
kfiles: $(KFILES)
.SUFFIXES: .k
.c.k: ; cem -c $*.c
# the next lines are generated automatically
# AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
alloc.o: alloc.h
alloc.o: assert.h
alloc.o: line.h
alloc.o: lookup.h
alloc.o: param.h
alloc.o: proinf.h
alloc.o: types.h
backward.o: ../../h/em_mnem.h
backward.o: ../../h/em_pseu.h
backward.o: ../../h/em_spec.h
backward.o: alloc.h
backward.o: assert.h
backward.o: ext.h
backward.o: line.h
backward.o: lookup.h
backward.o: param.h
backward.o: proinf.h
backward.o: types.h
cleanup.o: ../../h/em_mes.h
cleanup.o: ../../h/em_pseu.h
cleanup.o: ../../h/em_spec.h
cleanup.o: assert.h
cleanup.o: ext.h
cleanup.o: lookup.h
cleanup.o: param.h
cleanup.o: types.h
flow.o: ../../h/em_flag.h
flow.o: ../../h/em_mnem.h
flow.o: ../../h/em_spec.h
flow.o: alloc.h
flow.o: ext.h
flow.o: line.h
flow.o: optim.h
flow.o: param.h
flow.o: proinf.h
flow.o: types.h
getline.o: ../../h/em_flag.h
getline.o: ../../h/em_mes.h
getline.o: ../../h/em_pseu.h
getline.o: ../../h/em_spec.h
getline.o: alloc.h
getline.o: assert.h
getline.o: ext.h
getline.o: line.h
getline.o: lookup.h
getline.o: param.h
getline.o: proinf.h
getline.o: types.h
lookup.o: alloc.h
lookup.o: lookup.h
lookup.o: param.h
lookup.o: proinf.h
lookup.o: types.h
main.o: ../../h/em_spec.h
main.o: alloc.h
main.o: ext.h
main.o: param.h
main.o: types.h
mktab.o: ../../h/em_mnem.h
mktab.o: ../../h/em_spec.h
mktab.o: optim.h
mktab.o: param.h
mktab.o: pattern.h
mktab.o: scan.c
mktab.o: types.h
pattern.o: param.h
pattern.o: pattern.h
pattern.o: types.h
peephole.o: ../../h/em_mnem.h
peephole.o: ../../h/em_spec.h
peephole.o: alloc.h
peephole.o: assert.h
peephole.o: ext.h
peephole.o: line.h
peephole.o: lookup.h
peephole.o: optim.h
peephole.o: param.h
peephole.o: pattern.h
peephole.o: proinf.h
peephole.o: types.h
process.o: ../../h/em_pseu.h
process.o: ../../h/em_spec.h
process.o: alloc.h
process.o: assert.h
process.o: ext.h
process.o: line.h
process.o: lookup.h
process.o: param.h
process.o: proinf.h
process.o: types.h
putline.o: ../../h/em_flag.h
putline.o: ../../h/em_mnem.h
putline.o: ../../h/em_pseu.h
putline.o: ../../h/em_spec.h
putline.o: alloc.h
putline.o: assert.h
putline.o: ext.h
putline.o: line.h
putline.o: lookup.h
putline.o: optim.h
putline.o: param.h
putline.o: proinf.h
putline.o: types.h
reg.o: ../../h/em_mes.h
reg.o: ../../h/em_pseu.h
reg.o: ../../h/em_spec.h
reg.o: alloc.h
reg.o: assert.h
reg.o: ext.h
reg.o: line.h
reg.o: param.h
reg.o: proinf.h
reg.o: types.h
scan.o: stdio.h
special.o: param.h
special.o: types.h
util.o: assert.h
util.o: ext.h
util.o: lookup.h
util.o: optim.h
util.o: param.h
util.o: proinf.h
util.o: types.h
var.o: lookup.h
var.o: param.h
var.o: proinf.h
var.o: types.h

View File

@@ -1,448 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "assert.h"
#include "alloc.h"
#include "line.h"
#include "lookup.h"
#include "proinf.h"
/*
* (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
*
* Author: Hans van Staveren
*/
#ifdef USEMALLOC
short * myalloc();
#define newcore(size) myalloc(size)
#define oldcore(p,size) free(p)
#else
/* #define CORECHECK /* if defined tests are made to insure
each block occurs at most once */
#define CCHUNK 1024 /* number of shorts asked from system */
short *newcore(),*freshcore();
extern char *sbrk();
#ifdef COREDEBUG
int shortsasked=0;
#endif
#endif
/*
* The following two sizetables contain the sizes of the various kinds
* of line and argument structures.
* Care has been taken to make this table implementation independent,
* but if you think very hard you might find a compiler failing the
* assumptions made.
* A wasteful but safe approach is to replace every line of them by
* sizeof(line_t)
* and
* sizeof(arg_t)
* respectively.
*/
#define LBASE (sizeof(line_t)-sizeof(un_l_a))
int lsizetab[] = {
LBASE,
LBASE+sizeof(short),
LBASE+sizeof(offset),
LBASE+sizeof(num_p),
LBASE+sizeof(sym_p),
LBASE+sizeof(s_la_sval),
LBASE+sizeof(s_la_lval),
LBASE+sizeof(arg_p),
LBASE
};
#define ABASE (sizeof(arg_t)-sizeof(un_a_a))
int asizetab[] = {
ABASE+sizeof(offset),
ABASE+sizeof(num_p),
ABASE+sizeof(sym_p),
ABASE+sizeof(s_a_val),
ABASE+sizeof(argb_t),
ABASE+sizeof(s_a_con),
ABASE+sizeof(s_a_con),
ABASE+sizeof(s_a_con),
};
/*
* alloc routines:
* Two parts:
* 1) typed alloc and free routines
* 2) untyped raw core allocation
*/
/*
* PART 1
*/
line_p newline(optyp) int optyp; {
register line_p lnp;
register kind=optyp;
if (kind>OPMINI)
kind = OPMINI;
lnp = (line_p) newcore(lsizetab[kind]);
lnp->l_optyp = optyp;
return(lnp);
}
oldline(lnp) register line_p lnp; {
register kind=lnp->l_optyp&BMASK;
if (kind>OPMINI)
kind = OPMINI;
if (kind == OPLIST)
oldargs(lnp->l_a.la_arg);
oldcore((short *) lnp,lsizetab[kind]);
}
arg_p newarg(kind) int kind; {
register arg_p ap;
ap = (arg_p) newcore(asizetab[kind]);
ap->a_typ = kind;
return(ap);
}
oldargs(ap) register arg_p ap; {
register arg_p next;
while (ap != (arg_p) 0) {
next = ap->a_next;
switch(ap->a_typ) {
case ARGSTR:
oldargb(ap->a_a.a_string.ab_next);
break;
case ARGICN:
case ARGUCN:
case ARGFCN:
oldargb(ap->a_a.a_con.ac_con.ab_next);
break;
}
oldcore((short *) ap,asizetab[ap->a_typ]);
ap = next;
}
}
oldargb(abp) register argb_p abp; {
register argb_p next;
while (abp != (argb_p) 0) {
next = abp->ab_next;
oldcore((short *) abp,sizeof (argb_t));
abp = next;
}
}
reg_p newreg() {
return((reg_p) newcore(sizeof(reg_t)));
}
oldreg(rp) reg_p rp; {
oldcore((short *) rp,sizeof(reg_t));
}
num_p newnum() {
return((num_p) newcore(sizeof(num_t)));
}
oldnum(lp) num_p lp; {
oldcore((short *) lp,sizeof(num_t));
}
offset *newrom() {
return((offset *) newcore(MAXROM*sizeof(offset)));
}
sym_p newsym(len) int len; {
/*
* sym_t includes a 2 character s_name at the end
* extend this structure with len-2 characters
*/
return((sym_p) newcore(sizeof(sym_t) - 2 + len));
}
argb_p newargb() {
return((argb_p) newcore(sizeof(argb_t)));
}
#ifndef USEMALLOC
/******************************************************************/
/****** Start of raw core management package *****************/
/******************************************************************/
#define MAXSHORT 30 /* Maximum number of shorts one can ask for */
short *freelist[MAXSHORT];
typedef struct coreblock {
struct coreblock *co_next;
short co_size;
} core_t,*core_p;
#define SINC (sizeof(core_t)/sizeof(short))
#ifdef COREDEBUG
coreverbose() {
register size;
register short *p;
register sum;
sum = 0;
for(size=1;size<MAXSHORT;size++)
for (p=freelist[size];p!=0;p = *(short **) p)
sum += size;
fprintf(stderr,"Used core %u\n",(shortsasked-sum)*sizeof(short));
}
#endif
#ifdef SEPID
compactcore() {
register core_p corelist=0,tp,cl;
int size;
#ifdef COREDEBUG
fprintf(stderr,"Almost out of core\n");
#endif
for(size=SINC;size<MAXSHORT;size++) {
while ((tp = (core_p) freelist[size]) != (core_p) 0) {
freelist[size] = (short *) tp->co_next;
tp->co_size = size;
if (corelist==0 || tp<corelist) {
tp->co_next = corelist;
corelist = tp;
} else {
for(cl=corelist;cl->co_next != 0 && tp>cl->co_next;
cl = cl->co_next)
;
tp->co_next = cl->co_next;
cl->co_next = tp;
}
}
}
while (corelist != 0) {
while ((short *) corelist->co_next ==
(short *) corelist + corelist->co_size) {
corelist->co_size += corelist->co_next->co_size;
corelist->co_next = corelist->co_next->co_next;
}
assert(corelist->co_next==0 ||
(short *) corelist->co_next >
(short *) corelist + corelist->co_size);
while (corelist->co_size >= MAXSHORT+SINC) {
oldcore((short *) corelist + corelist->co_size-(MAXSHORT-1),
sizeof(short)*(MAXSHORT-1));
corelist->co_size -= MAXSHORT;
}
if (corelist->co_size >= MAXSHORT) {
oldcore((short *) corelist + corelist->co_size-SINC,
sizeof(short)*SINC);
corelist->co_size -= SINC;
}
cl = corelist->co_next;
oldcore((short *) corelist, sizeof(short)*corelist->co_size);
corelist = cl;
}
}
short *grabcore(size) int size; {
register short *p;
register trysize;
/*
* Desperate situation, can't get more core from system.
* Postpone giving up just a little bit by splitting up
* larger free blocks if possible.
* Algorithm is worst fit.
*/
assert(size<2*MAXSHORT);
for(trysize=2*MAXSHORT-2; trysize>size; trysize -= 2) {
p = freelist[trysize/sizeof(short)];
if ( p != (short *) 0) {
freelist[trysize/sizeof(short)] = *(short **) p;
oldcore(p+size/sizeof(short),trysize-size);
return(p);
}
}
/*
* Can't get more core from the biggies, try to combine the
* little ones. This is expensive but probably better than
* giving up.
*/
compactcore();
if ((p=freelist[size/sizeof(short)]) != 0) {
freelist[size/sizeof(short)] = * (short **) p;
return(p);
}
for(trysize=2*MAXSHORT-2; trysize>size; trysize -= 2) {
p = freelist[trysize/sizeof(short)];
if ( p != (short *) 0) {
freelist[trysize/sizeof(short)] = *(short **) p;
oldcore(p+size/sizeof(short),trysize-size);
return(p);
}
}
/*
* That's it then. Finished.
*/
return(0);
}
#endif /* SEPID */
short *newcore(size) int size; {
register short *p,*q;
if( size < 2*MAXSHORT ) {
if ((p=freelist[size/sizeof(short)]) != (short *) 0)
freelist[size/sizeof(short)] = *(short **) p;
else {
p = freshcore(size);
#ifdef SEPID
if (p == (short *) 0)
p = grabcore(size);
#endif
}
} else
p = freshcore(size);
if (p == 0)
error("out of memory");
for (q=p; size > 0 ; size -= sizeof(short))
*q++ = 0;
return(p);
}
#ifdef NOMALLOC
/*
* stdio uses malloc and free.
* you can use these as substitutes
*/
char *malloc(size) int size; {
/*
* malloc(III) is called by stdio,
* this routine is a substitute.
*/
return( (char *) newcore(size));
}
free() {
}
#endif
oldcore(p,size) short *p; int size; {
#ifdef CORECHECK
register short *cp;
#endif
assert(size<2*MAXSHORT);
#ifdef CORECHECK
for (cp=freelist[size/sizeof(short)]; cp != (short *) 0;
cp = (short *) *cp)
assert(cp != p);
#endif
*(short **) p = freelist[size/sizeof(short)];
freelist[size/sizeof(short)] = p;
}
short *ccur,*cend;
coreinit(p1,p2) short *p1,*p2; {
/*
* coreinit is called with the boundaries of a piece of
* memory that can be used for starters.
*/
ccur = p1;
cend = p2;
}
short *freshcore(size) int size; {
register short *temp;
static int cchunk=CCHUNK;
while(&ccur[size/sizeof(short)] >= cend && cchunk>0) {
do {
temp = (short *) sbrk(cchunk*sizeof(short));
if (temp == (short *) -1)
cchunk >>= 1;
else if (temp != cend)
ccur = cend = temp;
} while (temp == (short *) -1 && cchunk>0);
cend += cchunk;
#ifdef COREDEBUG
shortsasked += cchunk;
#endif
}
if (cchunk==0)
return(0);
temp = ccur;
ccur = &ccur[size/sizeof(short)];
return(temp);
}
#else /* USEMALLOC */
coreinit() {
/*
* Empty function, no initialization needed
*/
}
short *myalloc(size) register size; {
register short *p,*q;
extern char *malloc();
p = (short *)malloc(size);
if (p == 0)
error("out of memory");
for(q=p;size>0;size -= sizeof(short))
*q++ = 0;
return(p);
}
#endif

View File

@@ -1,55 +0,0 @@
/* $Header$ */
extern line_p newline();
extern offset *newrom();
extern sym_p newsym();
extern num_p newnum();
extern arg_p newarg();
extern argb_p newargb();
extern reg_p newreg();
extern oldline();
extern oldloc();
extern oldreg();
/* #define USEMALLOC /* if defined malloc() and free() are used */
/* #define COREDEBUG /* keep records and print statistics */
/*
* The next define gives if defined the number of pseudo's outside
* procedures that are collected without processing.
* If undefined all pseudo's will be collected but that may
* give trouble on small machines, because of lack of room.
*/
#define PSEUBETWEEN 200
#ifndef USEMALLOC
/*
* Now the real bitsqueezing starts.
* When running on a machine where code and data live in
* separate address-spaces it is worth putting in some extra
* code to save on probably less data.
*/
#define SEPID /* code and data in separate spaces */
/*
* If the stack segment and the data are separate as on a PDP11 under UNIX
* it is worth squeezing some shorts out of the stack page.
*/
#ifndef EM_WSIZE
/*
* Compiled with 'standard' C compiler
*/
#define STACKROOM 3200 /* number of shorts space in stack */
#else
/*
* Compiled with pcc, has trouble with lots of variables
*/
#define STACKROOM 2000
#endif
#else
#define STACKROOM 1 /* 0 gives problems */
#endif /* USEMALLOC */

View File

@@ -1,7 +0,0 @@
/* $Header$ */
#ifndef NDEBUG
#define assert(x) if(!(x)) badassertion(__FILE__,__LINE__)
#else
#define assert(x) /* nothing */
#endif

View File

@@ -1,187 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "assert.h"
#include "line.h"
#include "lookup.h"
#include "alloc.h"
#include "proinf.h"
#include "../../h/em_spec.h"
#include "../../h/em_pseu.h"
#include "../../h/em_mnem.h"
#include "ext.h"
/*
* (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
*
* Author: Hans van Staveren
*/
#define local(x) if (((x)->s_flags&SYMKNOWN) == 0)\
x->s_flags &= ~ SYMGLOBAL
#define global(x) if(((x)->s_flags&SYMKNOWN) == 0)\
x->s_flags |= SYMGLOBAL
#define DTYPHOL 1
#define DTYPBSS 2
#define DTYPCON 3
#define DTYPROM 4
byte curdtyp;
bool goodrom;
short curfrag = 3; /* see also peephole.c */
offset rombuf[MAXROM];
int rc;
backward() {
register line_p lnp;
line_p next;
register arg_p ap;
line_p i,p;
int n;
register sym_p sp;
i = p = (line_p) 0;
curdtyp=0;
for (lnp = curpro.lastline; lnp != (line_p) 0; lnp = next) {
next = lnp->l_next;
switch(lnp->l_optyp) {
case OPSYMBOL:
global(lnp->l_a.la_sp);
break;
case OPSVAL:
global(lnp->l_a.la_sval.lasv_sp);
break;
case OPLVAL:
global(lnp->l_a.la_lval.lalv_sp);
break;
case OPLIST:
ap = lnp->l_a.la_arg;
while (ap != (arg_p) 0 ) {
switch(ap->a_typ) {
case ARGSYM:
global(ap->a_a.a_sp);
break;
case ARGVAL:
global(ap->a_a.a_val.av_sp);
}
ap = ap->a_next;
}
break;
}
/*
* references to symbols are processed now.
* for plain instructions nothing else is needed
*/
switch(lnp->l_instr&BMASK) {
/*
* count all local occurences for register counts;
* op_lal is omitted and not by accident.
*/
case op_del:
case op_inl:
case op_ldl:
case op_lil:
case op_lol:
case op_sdl:
case op_sil:
case op_stl:
case op_zrl:
switch(lnp->l_optyp) {
case OPNO:
case OPNUMLAB:
case OPSYMBOL:
case OPSVAL:
case OPLVAL:
case OPLIST:
break;
case OPOFFSET:
incregusage(lnp->l_a.la_offset);
break;
case OPSHORT:
incregusage((offset)lnp->l_a.la_short);
break;
default:
incregusage((offset)(lnp->l_optyp&BMASK)-Z_OPMINI);
break;
}
/* fall through !! */
default:
assert((lnp->l_instr&BMASK)<=op_last);
lnp->l_next = i;
i = lnp;
continue;
case ps_sym:
sp = lnp->l_a.la_sp;
local(sp);
if (curdtyp == DTYPROM && goodrom) {
sp->s_rom = newrom();
for (n=0;n<rc;n++)
sp->s_rom[n] = rombuf[n];
}
sp->s_frag = curfrag;
break;
case ps_hol:
curdtyp = DTYPHOL;
curfrag++;
break;
case ps_bss:
curdtyp = DTYPBSS;
curfrag++;
break;
case ps_con:
if (curdtyp != DTYPCON) {
curdtyp = DTYPCON;
curfrag++;
}
break;
case ps_rom:
if (curdtyp != DTYPROM) {
curdtyp = DTYPROM;
curfrag++;
}
ap = lnp->l_a.la_arg;
rc = 0;
while (ap != (arg_p) 0 && rc < MAXROM) {
if (ap->a_typ == ARGOFF) {
rombuf[rc++] = ap->a_a.a_offset;
ap = ap->a_next;
} else
ap = (arg_p) 0;
}
goodrom = (rc >= 2);
break;
case ps_mes:
break;
case ps_inp:
case ps_ina:
local(lnp->l_a.la_sp);
case ps_exp:
case ps_exa:
case ps_exc:
oldline(lnp);
continue;
}
lnp->l_next = p;
p = lnp;
}
if (prodepth != 0)
local(curpro.symbol);
instrs = i; pseudos = p; curpro.lastline = (line_p) 0;
}

View File

@@ -1,65 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "assert.h"
#include "../../h/em_pseu.h"
#include "../../h/em_spec.h"
#include "../../h/em_mes.h"
#include "lookup.h"
#include "ext.h"
/*
* (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
*
* Author: Hans van Staveren
*/
cleanup() {
FILE *infile;
register c;
register sym_p *spp,sp;
for (spp=symhash;spp< &symhash[NSYMHASH];spp++)
for (sp = *spp; sp != (sym_p) 0; sp = sp->s_next)
if ((sp->s_flags & SYMOUT) == 0)
outdef(sp);
if(!Lflag)
return;
c=fclose(outfile);
assert(c != EOF);
outfile = stdout;
infile = fopen(template,"r");
if (infile == NULL)
error("temp file disappeared");
outshort(sp_magic);
outinst(ps_mes);
outint(ms_ext);
for (spp=symhash;spp< &symhash[NSYMHASH];spp++)
for (sp = *spp; sp != (sym_p) 0; sp = sp->s_next)
if ((sp->s_flags&(SYMDEF|SYMGLOBAL)) == (SYMDEF|SYMGLOBAL))
outsym(sp);
putc(sp_cend,outfile);
while ( (c=getc(infile)) != EOF)
putc(c,outfile);
c=fclose(infile);
assert(c != EOF);
c=unlink(template);
assert(c == 0);
}

View File

@@ -1,35 +0,0 @@
.\" $Header$
.TH EM_OPT VI
.ad
.SH NAME
em_opt \- EM peephole optimizer
.SH SYNOPSIS
/usr/em/lib/em_opt [-Ln] [ argument ]
.SH DESCRIPTION
Em_opt reads a compact EM-program, argument or standard input,
and produces another compact EM program on standard output
that is functionally equivalent,
but smaller.
Some other functions are here that make this program mandatory
before running a codegenerator,
it may be left out when interpretation is wanted.
Flags recognized are:
.IP -L
Make a library module.
This means that the output will start with a message giving
the names of all exported entities in this module.
.IP -n
Do not optimize.
No peephole optimizations will be performed,
other functions will be carried out.
.SH "FILES"
/usr/tmp/emopt??????, is used when the -L flag is given only.
.SH "SEE ALSO"
ack(I)
.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 AUTHOR
Hans van Staveren, Vrije Universiteit

View File

@@ -1,16 +0,0 @@
/* $Header$ */
#ifndef FILE
#include <stdio.h>
#endif
extern unsigned linecount;
extern int prodepth;
extern bool Lflag;
extern bool nflag;
extern byte em_flag[];
extern line_p instrs,pseudos;
extern FILE *outfile;
extern char template[];
extern offset wordsize;
extern offset pointersize;
extern char *progname;

View File

@@ -1,127 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "../../h/em_flag.h"
#include "../../h/em_spec.h"
#include "../../h/em_mnem.h"
#include "alloc.h"
#include "line.h"
#include "proinf.h"
#include "optim.h"
#include "ext.h"
/*
* (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
*
* Author: Hans van Staveren
*/
flow() {
findreach(); /* determine reachable labels */
cleaninstrs(); /* throw away unreachable code */
}
findreach() {
register num_p *npp,np;
reach(instrs);
for(npp=curpro.numhash;npp< &curpro.numhash[NNUMHASH]; npp++)
for(np= *npp; np != (num_p) 0 ; np = np->n_next)
if (np->n_flags&NUMDATA) {
np->n_repl->n_flags |= NUMREACH;
np->n_repl->n_jumps++;
if (!(np->n_flags&NUMSCAN)) {
np->n_flags |= NUMSCAN;
reach(np->n_line->l_next);
}
}
}
reach(lnp) register line_p lnp; {
register num_p np;
for (;lnp != (line_p) 0; lnp = lnp->l_next) {
if(lnp->l_optyp == OPNUMLAB) {
/*
* Branch instruction or label
*/
np = lnp->l_a.la_np;
if ((lnp->l_instr&BMASK) != op_lab)
np = np->n_repl;
np->n_flags |= NUMREACH;
if (!(np->n_flags&NUMSCAN)) {
np->n_flags |= NUMSCAN;
reach(np->n_line->l_next);
}
if ((lnp->l_instr&BMASK) == op_lab)
return;
else
np->n_jumps++;
}
if ((em_flag[(lnp->l_instr&BMASK)-sp_fmnem]&EM_FLO)==FLO_T)
return;
}
}
cleaninstrs() {
register line_p *lpp,lp,*lastbra;
bool reachable,superfluous;
int instr;
lpp = &instrs; lastbra = (line_p *) 0; reachable = TRUE;
while ((lp = *lpp) != (line_p) 0) {
instr = lp->l_instr&BMASK;
if (instr == op_lab) {
if ((lp->l_a.la_np->n_flags&NUMREACH) != 0) {
reachable = TRUE;
if (lastbra != (line_p *) 0
&& (*lastbra)->l_next == lp
&& (*lastbra)->l_a.la_np->n_repl==lp->l_a.la_np) {
oldline(*lastbra);
OPTIM(O_BRALAB);
lpp = lastbra;
*lpp = lp;
lastbra = (line_p *) 0;
lp->l_a.la_np->n_jumps--;
}
}
if ( lp->l_a.la_np->n_repl != lp->l_a.la_np ||
((lp->l_a.la_np->n_flags&NUMDATA)==0 &&
lp->l_a.la_np->n_jumps == 0))
superfluous = TRUE;
else
superfluous = FALSE;
} else
superfluous = FALSE;
if ( (!reachable) || superfluous) {
lp = lp->l_next;
oldline(*lpp);
OPTIM(O_UNREACH);
*lpp = lp;
} else {
if ( instr <= sp_lmnem &&
(em_flag[instr-sp_fmnem]&EM_FLO)==FLO_T) {
reachable = FALSE;
if ((lp->l_instr&BMASK) == op_bra)
lastbra = lpp;
}
lpp = &lp->l_next;
}
}
}

View File

@@ -1,556 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "assert.h"
#include "line.h"
#include "lookup.h"
#include "alloc.h"
#include "proinf.h"
#include "../../h/em_spec.h"
#include "../../h/em_pseu.h"
#include "../../h/em_flag.h"
#include "../../h/em_mes.h"
#include "ext.h"
/*
* (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
*
* Author: Hans van Staveren
*/
static short tabval; /* temp store for shorts */
static offset tabval2; /* temp store for offsets */
static char string[IDL+1]; /* temp store for names */
/*
* The next constants are close to sp_cend for fast switches
*/
#define INST 256 /* instruction: number in tabval */
#define PSEU 257 /* pseudo: number in tabval */
#define ILBX 258 /* label: number in tabval */
#define DLBX 259 /* symbol: name in string[] */
#define CSTX1 260 /* short constant: stored in tabval */
#define CSTX2 261 /* offset: value in tabval2 */
#define VALX1 262 /* symbol+short: in string[] and tabval */
#define VALX2 263 /* symbol+offset: in string[] and tabval2 */
#define ATEOF 264 /* bumped into end of file */
#define readbyte getchar
short readshort() {
register int l_byte, h_byte;
l_byte = readbyte();
h_byte = readbyte();
if ( h_byte>=128 ) h_byte -= 256 ;
return l_byte | (h_byte*256) ;
}
#ifdef LONGOFF
offset readoffset() {
register long l;
register int h_byte;
l = readbyte();
l |= ((unsigned) readbyte())*256 ;
l |= readbyte()*256L*256L ;
h_byte = readbyte() ;
if ( h_byte>=128 ) h_byte -= 256 ;
return l | (h_byte*256L*256*256L) ;
}
#endif
draininput() {
/*
* called when MES ERR is encountered.
* Drain input in case it is a pipe.
*/
while (getchar() != EOF)
;
}
short getint() {
switch(table2()) {
default: error("int expected");
case CSTX1:
return(tabval);
}
}
sym_p getsym(status) int status; {
switch(table2()) {
default:
error("symbol expected");
case DLBX:
return(symlookup(string,status,0));
case sp_pnam:
return(symlookup(string,status,SYMPRO));
}
}
offset getoff() {
switch (table2()) {
default: error("offset expected");
case CSTX1:
return((offset) tabval);
#ifdef LONGOFF
case CSTX2:
return(tabval2);
#endif
}
}
make_string(n) int n; {
register char *s;
extern char *sprintf();
s=sprintf(string,".%u",n);
assert(s == string);
}
inident() {
register n;
register char *p = string;
register c;
n = getint();
while (n--) {
c = readbyte();
if (p<&string[IDL])
*p++ = c;
}
*p++ = 0;
}
int table3(n) int n; {
switch (n) {
case sp_ilb1: tabval = readbyte(); return(ILBX);
case sp_ilb2: tabval = readshort(); return(ILBX);
case sp_dlb1: make_string(readbyte()); return(DLBX);
case sp_dlb2: make_string(readshort()); return(DLBX);
case sp_dnam: inident(); return(DLBX);
case sp_pnam: inident(); return(n);
case sp_cst2: tabval = readshort(); return(CSTX1);
#ifdef LONGOFF
case sp_cst4: tabval2 = readoffset(); return(CSTX2);
#endif
case sp_doff: if (table2()!=DLBX) error("symbol expected");
switch(table2()) {
default: error("offset expected");
case CSTX1: return(VALX1);
#ifdef LONGOFF
case CSTX2: return(VALX2);
#endif
}
default: return(n);
}
}
int table1() {
register n;
n = readbyte();
if (n == EOF)
return(ATEOF);
if ((n <= sp_lmnem) && (n >= sp_fmnem)) {
tabval = n;
return(INST);
}
if ((n <= sp_lpseu) && (n >= sp_fpseu)) {
tabval = n;
return(PSEU);
}
if ((n < sp_filb0 + sp_nilb0) && (n >= sp_filb0)) {
tabval = n - sp_filb0;
return(ILBX);
}
return(table3(n));
}
int table2() {
register n;
n = readbyte();
if ((n < sp_fcst0 + sp_ncst0) && (n >= sp_fcst0)) {
tabval = n - sp_zcst0;
return(CSTX1);
}
return(table3(n));
}
getlines() {
register line_p lnp;
register instr;
for(;;) {
linecount++;
switch(table1()) {
default:
error("unknown instruction byte");
/* NOTREACHED */
case ATEOF:
if (prodepth!=0)
error("procedure unterminated at eof");
process();
return;
case INST:
tstinpro();
instr = tabval;
break;
case DLBX:
lnp = newline(OPSYMBOL);
lnp->l_instr = ps_sym;
lnp->l_a.la_sp= symlookup(string,DEFINING,0);
lnp->l_next = curpro.lastline;
curpro.lastline = lnp;
continue;
case ILBX:
tstinpro();
lnp = newline(OPNUMLAB);
lnp->l_instr = op_lab;
lnp->l_a.la_np = numlookup((unsigned) tabval);
if (lnp->l_a.la_np->n_line != (line_p) 0)
error("label %u multiple defined",(unsigned) tabval);
lnp->l_a.la_np->n_line = lnp;
lnp->l_next = curpro.lastline;
curpro.lastline = lnp;
continue;
case PSEU:
if(inpseudo(tabval))
return;
continue;
}
/*
* Now we have an instruction number in instr
* There might be an operand, look for it
*/
if ((em_flag[instr-sp_fmnem]&EM_PAR)==PAR_NO) {
lnp = newline(OPNO);
} else switch(table2()) {
default:
error("unknown offset byte");
case sp_cend:
lnp = newline(OPNO);
break;
case CSTX1:
if ((em_flag[instr-sp_fmnem]&EM_PAR)!= PAR_B) {
if (CANMINI(tabval))
lnp = newline(tabval+Z_OPMINI);
else {
lnp = newline(OPSHORT);
lnp->l_a.la_short = tabval;
}
} else {
lnp = newline(OPNUMLAB);
lnp->l_a.la_np = numlookup((unsigned) tabval);
}
break;
#ifdef LONGOFF
case CSTX2:
lnp = newline(OPOFFSET);
lnp->l_a.la_offset = tabval2;
break;
#endif
case ILBX:
tstinpro();
lnp = newline(OPNUMLAB);
lnp->l_a.la_np = numlookup((unsigned) tabval);
break;
case DLBX:
lnp = newline(OPSYMBOL);
lnp->l_a.la_sp = symlookup(string,OCCURRING,0);
break;
case sp_pnam:
lnp = newline(OPSYMBOL);
lnp->l_a.la_sp = symlookup(string,OCCURRING,SYMPRO);
break;
case VALX1:
lnp = newline(OPSVAL);
lnp->l_a.la_sval.lasv_sp = symlookup(string,OCCURRING,0);
lnp->l_a.la_sval.lasv_short = tabval;
break;
#ifdef LONGOFF
case VALX2:
lnp = newline(OPLVAL);
lnp->l_a.la_lval.lalv_sp = symlookup(string,OCCURRING,0);
lnp->l_a.la_lval.lalv_offset = tabval2;
break;
#endif
}
lnp->l_instr = instr;
lnp->l_next = curpro.lastline;
curpro.lastline = lnp;
}
}
argstring(length,abp) offset length; register argb_p abp; {
while (length--) {
if (abp->ab_index == NARGBYTES)
abp = abp->ab_next = newargb();
abp->ab_contents[abp->ab_index++] = readbyte();
}
}
line_p arglist(n) int n; {
line_p lnp;
register arg_p ap,*app;
bool moretocome;
offset length;
/*
* creates an arglist with n elements
* if n == 0 the arglist is variable and terminated by sp_cend
*/
lnp = newline(OPLIST);
app = &lnp->l_a.la_arg;
moretocome = TRUE;
do {
switch(table2()) {
default:
error("unknown byte in arglist");
case CSTX1:
tabval2 = (offset) tabval;
case CSTX2:
*app = ap = newarg(ARGOFF);
ap->a_a.a_offset = tabval2;
app = &ap->a_next;
break;
case ILBX:
tstinpro();
*app = ap = newarg(ARGNUM);
ap->a_a.a_np = numlookup((unsigned) tabval);
ap->a_a.a_np->n_flags |= NUMDATA;
app = &ap->a_next;
break;
case DLBX:
*app = ap = newarg(ARGSYM);
ap->a_a.a_sp = symlookup(string,OCCURRING,0);
app = &ap->a_next;
break;
case sp_pnam:
*app = ap = newarg(ARGSYM);
ap->a_a.a_sp = symlookup(string,OCCURRING,SYMPRO);
app = &ap->a_next;
break;
case VALX1:
tabval2 = (offset) tabval;
case VALX2:
*app = ap = newarg(ARGVAL);
ap->a_a.a_val.av_sp = symlookup(string,OCCURRING,0);
ap->a_a.a_val.av_offset = tabval2;
app = &ap->a_next;
break;
case sp_scon:
*app = ap = newarg(ARGSTR);
length = getoff();
argstring(length,&ap->a_a.a_string);
app = &ap->a_next;
break;
case sp_icon:
*app = ap = newarg(ARGICN);
goto casecon;
case sp_ucon:
*app = ap = newarg(ARGUCN);
goto casecon;
case sp_fcon:
*app = ap = newarg(ARGFCN);
casecon:
length = getint();
ap->a_a.a_con.ac_length = (short) length;
argstring(getoff(),&ap->a_a.a_con.ac_con);
app = &ap->a_next;
break;
case sp_cend:
moretocome = FALSE;
}
if (n && (--n) == 0)
moretocome = FALSE;
} while (moretocome);
return(lnp);
}
offset aoff(ap,n) register arg_p ap; {
while (n>0) {
if (ap != (arg_p) 0)
ap = ap->a_next;
n--;
}
if (ap == (arg_p) 0)
error("too few parameters");
if (ap->a_typ != ARGOFF)
error("offset expected");
return(ap->a_a.a_offset);
}
int inpseudo(n) short n; {
register line_p lnp,head,tail;
short n1,n2;
proinf savearea;
#ifdef PSEUBETWEEN
static int pcount=0;
if (pcount++ >= PSEUBETWEEN && prodepth==0) {
process();
pcount=0;
}
#endif
switch(n) {
default:
error("unknown pseudo");
case ps_bss:
case ps_hol:
lnp = arglist(3);
break;
case ps_rom:
case ps_con:
lnp = arglist(0);
break;
case ps_ina:
case ps_inp:
case ps_exa:
case ps_exp:
lnp = newline(OPSYMBOL);
lnp->l_a.la_sp = getsym(NOTHING);
break;
case ps_exc:
n1 = getint(); n2 = getint();
if (n1 != 0 && n2 != 0) {
tail = curpro.lastline;
while (--n2) tail = tail->l_next;
head = tail;
while (n1--) head = head->l_next;
lnp = tail->l_next;
tail->l_next = head->l_next;
head->l_next = curpro.lastline;
curpro.lastline = lnp;
}
lnp = newline(OPNO);
break;
case ps_mes:
lnp = arglist(0);
switch((int) aoff(lnp->l_a.la_arg,0)) {
case ms_err:
draininput(); exit(-1);
case ms_opt:
nflag = TRUE; break;
case ms_emx:
wordsize = aoff(lnp->l_a.la_arg,1);
pointersize = aoff(lnp->l_a.la_arg,2);
#ifndef LONGOFF
if (wordsize>2)
error("This optimizer cannot handle wordsize>2");
#endif
break;
case ms_gto:
curpro.gtoproc=1;
/* Treat as empty mes ms_reg */
case ms_reg:
tstinpro();
regvar(lnp->l_a.la_arg->a_next);
oldline(lnp);
lnp=newline(OPNO);
n=ps_exc; /* kludge to force out this line */
break;
}
break;
case ps_pro:
if (prodepth>0)
savearea = curpro;
else
process();
curpro.symbol = getsym(DEFINING);
switch(table2()) {
case sp_cend:
curpro.localbytes = (offset) -1;
break;
case CSTX1:
tabval2 = (offset) tabval;
case CSTX2:
curpro.localbytes = tabval2;
break;
default:
error("bad second arg of PRO");
}
prodepth++;
curpro.gtoproc=0;
if (prodepth>1) {
register i;
curpro.lastline = (line_p) 0;
curpro.freg = (reg_p) 0;
for(i=0;i<NNUMHASH;i++)
curpro.numhash[i] = (num_p) 0;
getlines();
curpro = savearea;
prodepth--;
}
return(0);
case ps_end:
if (prodepth==0)
error("END misplaced");
switch(table2()) {
case sp_cend:
if (curpro.localbytes == (offset) -1)
error("bytes for locals still unknown");
break;
case CSTX1:
tabval2 = (offset) tabval;
case CSTX2:
if (curpro.localbytes != (offset) -1 && curpro.localbytes != tabval2)
error("inconsistency in number of bytes for locals");
curpro.localbytes = tabval2;
break;
}
process();
curpro.symbol = (sym_p) 0;
if (prodepth==1) {
prodepth=0;
#ifdef PSEUBETWEEN
pcount=0;
#endif
return(0);
} else
return(1);
}
lnp->l_instr = n;
lnp->l_next = curpro.lastline;
curpro.lastline = lnp;
return(0);
}
tstinpro() {
if (prodepth==0)
error("This is not allowed outside a procedure");
}

View File

@@ -1,88 +0,0 @@
/* $Header$ */
#define NARGBYTES 14
struct argbytes {
argb_p ab_next;
short ab_index;
char ab_contents[NARGBYTES];
};
typedef struct {
sym_p av_sp;
offset av_offset;
} s_a_val;
typedef struct {
short ac_length;
argb_t ac_con;
} s_a_con;
typedef union {
offset a_offset;
num_p a_np;
sym_p a_sp;
s_a_val a_val;
argb_t a_string;
s_a_con a_con;
} un_a_a;
struct arg {
arg_p a_next;
short a_typ;
un_a_a a_a;
};
/* possible values for .a_typ
*/
#define ARGOFF 0
#define ARGNUM 1
#define ARGSYM 2
#define ARGVAL 3
#define ARGSTR 4
#define ARGICN 5
#define ARGUCN 6
#define ARGFCN 7
typedef struct {
sym_p lasv_sp;
short lasv_short;
} s_la_sval;
typedef struct {
sym_p lalv_sp;
offset lalv_offset;
} s_la_lval;
typedef union {
short la_short;
offset la_offset;
num_p la_np;
sym_p la_sp;
s_la_sval la_sval;
s_la_lval la_lval;
arg_p la_arg;
} un_l_a;
struct line {
line_p l_next; /* maintains linked list */
byte l_instr; /* instruction number */
byte l_optyp; /* specifies what follows */
un_l_a l_a;
};
/* Possible values for .l_optyp */
#define OPNO 0 /* no operand */
#define OPSHORT 1 /* 16 bit number */
#define OPOFFSET 2 /* 16 or 32 bit number */
#define OPNUMLAB 3 /* local label for branches */
#define OPSYMBOL 4 /* global label or procedurename */
#define OPSVAL 5 /* symbol + 16 bit constant */
#define OPLVAL 6 /* symbol + 16 or 32 bit constant */
#define OPLIST 7 /* operand list for some pseudos */
#define OPMINI 8 /* start of minis */
#define Z_OPMINI (OPMINI+100) /* tunable */
#define CANMINI(x) ((x)>=OPMINI-Z_OPMINI && (x)<256-Z_OPMINI)

View File

@@ -1,94 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "lookup.h"
#include "alloc.h"
#include "proinf.h"
/*
* (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
*
* Author: Hans van Staveren
*/
unsigned hash(string) char *string; {
register char *p;
register unsigned i,sum;
for (sum=i=0,p=string;*p;i += 3)
sum ^= (*p++)<<(i&07);
return(sum);
}
sym_p symlookup(name,status,flags) char *name; int status,flags; {
register sym_p *spp,sp;
register i;
static short genfrag = 32767;
spp = &symhash[hash(name)%NSYMHASH];
while (*spp != (sym_p) 0)
if (strncmp((*spp)->s_name,name,IDL)==0) {
sp = *spp;
if ((sp->s_flags^flags)&SYMPRO)
error("%s is both proc and datalabel",name);
if (status == DEFINING) {
if (sp->s_flags&SYMDEF)
error("redefined symbol %s",name);
sp->s_flags |= SYMDEF;
}
return(sp);
} else
spp = &(*spp)->s_next;
/*
* symbol not found, enter in table
*/
i = strlen(name) + 1;
if (i & 1)
i++;
if (i > IDL)
i = IDL;
*spp = sp = newsym(i);
strncpy(sp->s_name,name,i);
sp->s_flags = flags;
if (status == DEFINING)
sp->s_flags |= SYMDEF;
sp->s_frag = genfrag--;
return(sp);
}
num_p numlookup(number) unsigned number; {
register num_p *npp, np;
npp = &curpro.numhash[number%NNUMHASH];
while (*npp != (num_p) 0)
if ((*npp)->n_number == number)
return(*npp);
else
npp = &(*npp)->n_next;
/*
* local label not found, enter in tabel
*/
*npp = np = newnum();
np->n_number = number;
np->n_repl = np;
return(np);
}

View File

@@ -1,25 +0,0 @@
/* $Header$ */
#define IDL 100
struct sym {
sym_p s_next;
offset *s_rom;
short s_flags;
short s_frag;
offset s_value;
char s_name[2]; /* to be extended up to IDL */
};
/* contents of .s_flags */
#define SYMPRO 000001
#define SYMGLOBAL 000002
#define SYMKNOWN 000004
#define SYMOUT 000010
#define SYMDEF 000020
#define NSYMHASH 127
extern sym_p symhash[NSYMHASH],symlookup();
#define OCCURRING 0
#define DEFINING 1
#define NOTHING 2

View File

@@ -1,77 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "alloc.h"
#include "../../h/em_spec.h"
#include "ext.h"
/*
* (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
*
* Author: Hans van Staveren
*/
/*
* Main program for EM optimizer
*/
main(argc,argv) int argc; char *argv[]; {
short somespace[STACKROOM];
progname = argv[0];
while (argc-->1 && **++argv == '-')
flags(*argv);
if (argc>1) {
fprintf(stderr,"Usage: %s [-Ln] [name]\n",progname);
exit(-1);
}
if (argc)
if (freopen(*argv,"r",stdin) == NULL)
error("Cannot open %s",*argv);
fileinit();
coreinit(somespace,somespace+STACKROOM);
getlines();
cleanup();
return(0);
}
flags(s) register char *s; {
for (s++;*s;s++)
switch(*s) {
case 'L': Lflag = TRUE; break;
case 'n': nflag = TRUE; break;
}
}
fileinit() {
char *mktemp();
short readshort();
if (readshort() != (short) sp_magic)
error("wrong input file");
if (Lflag) {
outfile = fopen(mktemp(template),"w");
if (outfile == NULL)
error("can't create %s",template);
} else {
outfile = stdout;
outshort(sp_magic);
}
}

View File

@@ -1,15 +0,0 @@
: '$Header$'
for extension in c y
do
for file in *.$extension
do ofile=`basename $file .$extension`.o
grep '^# *include.*"' $file|sed "s/.*\"\(.*\)\".*/$ofile: \1/"
done
done | sort -u >depend
ed - Makefile <<'!'
/AUTOAUTOAUTO/+,$d
$r depend
w
q
!
rm -f depend

View File

@@ -1,366 +0,0 @@
%{
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "pattern.h"
#include "../../h/em_spec.h"
#include "../../h/em_mnem.h"
#include "optim.h"
/*
* (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
*
* Author: Hans van Staveren
*/
#define MAXNODES 1000
expr_t nodes[MAXNODES];
expr_p lastnode = nodes+1;
int curind,prevind;
int patlen,maxpatlen,rpllen;
int lino = 1;
int patno=1;
#define MAX 100
int patmnem[MAX],rplmnem[MAX],rplexpr[MAX];
byte nparam[N_EX_OPS];
bool nonumlab[N_EX_OPS];
bool onlyconst[N_EX_OPS];
int nerrors=0;
%}
%union {
int y_int;
}
%left OR2
%left AND2
%left OR1
%left XOR1
%left AND1
%left CMPEQ,CMPNE
%left CMPLT,CMPLE,CMPGT,CMPGE
%left RSHIFT,LSHIFT
%left ARPLUS,ARMINUS
%left ARTIMES,ARDIVIDE,ARMOD
%nonassoc NOT,COMP,UMINUS
%nonassoc '$'
%token SFIT,UFIT,NOTREG,PSIZE,WSIZE,DEFINED,SAMESIGN,ROM,ROTATE
%token <y_int> MNEM
%token <y_int> NUMBER
%type <y_int> expr,argno,optexpr
%start patternlist
%%
patternlist
: /* empty */
| patternlist '\n'
| patternlist pattern
;
pattern :
mnemlist optexpr ':' replacement '\n'
{ register i;
outbyte(0); outshort(prevind); prevind=curind-3;
out(patlen);
for (i=0;i<patlen;i++) outbyte(patmnem[i]);
out($2);
out(rpllen);
for (i=0;i<rpllen;i++) {
outbyte(rplmnem[i]);
out(rplexpr[i]);
}
#ifdef DIAGOPT
outshort(patno);
#endif
patno++;
printf("\n");
if (patlen>maxpatlen) maxpatlen=patlen;
}
| error '\n'
{ yyerrok; }
;
replacement
: expr /* special optimization */
{
#ifdef ALLOWSPECIAL
rpllen=1; rplmnem[0]=0; rplexpr[0]=$1;
#else
yyerror("No specials allowed");
#endif
}
| repllist
;
repllist: /* empty */
{ rpllen=0; }
| repllist repl
;
repl : MNEM optexpr
{ rplmnem[rpllen] = $1; rplexpr[rpllen++] = $2; }
;
mnemlist: MNEM
{ patlen=0; patmnem[patlen++] = $1; }
| mnemlist MNEM
{ patmnem[patlen++] = $2; }
;
optexpr : /* empty */
{ $$ = 0; }
| expr
;
expr
: '$' argno
{ $$ = lookup(0,EX_ARG,$2,0); }
| NUMBER
{ $$ = lookup(0,EX_CON,(int)(short)$1,0); }
| PSIZE
{ $$ = lookup(0,EX_POINTERSIZE,0,0); }
| WSIZE
{ $$ = lookup(0,EX_WORDSIZE,0,0); }
| DEFINED '(' expr ')'
{ $$ = lookup(0,EX_DEFINED,$3,0); }
| SAMESIGN '(' expr ',' expr ')'
{ $$ = lookup(1,EX_SAMESIGN,$3,$5); }
| SFIT '(' expr ',' expr ')'
{ $$ = lookup(0,EX_SFIT,$3,$5); }
| UFIT '(' expr ',' expr ')'
{ $$ = lookup(0,EX_UFIT,$3,$5); }
| ROTATE '(' expr ',' expr ')'
{ $$ = lookup(0,EX_ROTATE,$3,$5); }
| NOTREG '(' expr ')'
{ $$ = lookup(0,EX_NOTREG,$3,0); }
| ROM '(' argno ',' expr ')'
{ $$ = lookup(0,EX_ROM,$3,$5); }
| '(' expr ')'
{ $$ = $2; }
| expr CMPEQ expr
{ $$ = lookup(1,EX_CMPEQ,$1,$3); }
| expr CMPNE expr
{ $$ = lookup(1,EX_CMPNE,$1,$3); }
| expr CMPGT expr
{ $$ = lookup(0,EX_CMPGT,$1,$3); }
| expr CMPGE expr
{ $$ = lookup(0,EX_CMPGE,$1,$3); }
| expr CMPLT expr
{ $$ = lookup(0,EX_CMPLT,$1,$3); }
| expr CMPLE expr
{ $$ = lookup(0,EX_CMPLE,$1,$3); }
| expr OR2 expr
{ $$ = lookup(0,EX_OR2,$1,$3); }
| expr AND2 expr
{ $$ = lookup(0,EX_AND2,$1,$3); }
| expr OR1 expr
{ $$ = lookup(1,EX_OR1,$1,$3); }
| expr XOR1 expr
{ $$ = lookup(1,EX_XOR1,$1,$3); }
| expr AND1 expr
{ $$ = lookup(1,EX_AND1,$1,$3); }
| expr ARPLUS expr
{ $$ = lookup(1,EX_PLUS,$1,$3); }
| expr ARMINUS expr
{ $$ = lookup(0,EX_MINUS,$1,$3); }
| expr ARTIMES expr
{ $$ = lookup(1,EX_TIMES,$1,$3); }
| expr ARDIVIDE expr
{ $$ = lookup(0,EX_DIVIDE,$1,$3); }
| expr ARMOD expr
{ $$ = lookup(0,EX_MOD,$1,$3); }
| expr LSHIFT expr
{ $$ = lookup(0,EX_LSHIFT,$1,$3); }
| expr RSHIFT expr
{ $$ = lookup(0,EX_RSHIFT,$1,$3); }
| ARPLUS expr %prec UMINUS
{ $$ = $2; }
| ARMINUS expr %prec UMINUS
{ $$ = lookup(0,EX_UMINUS,$2,0); }
| NOT expr
{ $$ = lookup(0,EX_NOT,$2,0); }
| COMP expr
{ $$ = lookup(0,EX_COMP,$2,0); }
;
argno : NUMBER
{ if ($1<1 || $1>patlen) {
YYERROR;
}
$$ = (int) $1;
}
;
%%
extern char em_mnem[][4];
#define HASHSIZE (2*(sp_lmnem-sp_fmnem))
struct hashmnem {
char h_name[3];
byte h_value;
} hashmnem[HASHSIZE];
inithash() {
register i;
enter("lab",op_lab);
enter("LLP",op_LLP);
enter("LEP",op_LEP);
enter("SLP",op_SLP);
enter("SEP",op_SEP);
for(i=0;i<=sp_lmnem-sp_fmnem;i++)
enter(em_mnem[i],i+sp_fmnem);
}
unsigned hashname(name) register char *name; {
register unsigned h;
h = (*name++)&BMASK;
h = (h<<4)^((*name++)&BMASK);
h = (h<<4)^((*name++)&BMASK);
return(h);
}
enter(name,value) char *name; {
register unsigned h;
h=hashname(name)%HASHSIZE;
while (hashmnem[h].h_name[0] != 0)
h = (h+1)%HASHSIZE;
strncpy(hashmnem[h].h_name,name,3);
hashmnem[h].h_value = value;
}
int mlookup(name) char *name; {
register unsigned h;
h = hashname(name)%HASHSIZE;
while (strncmp(hashmnem[h].h_name,name,3) != 0 &&
hashmnem[h].h_name[0] != 0)
h = (h+1)%HASHSIZE;
return(hashmnem[h].h_value&BMASK); /* 0 if not found */
}
main() {
inithash();
initio();
yyparse();
if (nerrors==0)
printnodes();
return nerrors;
}
yyerror(s) char *s; {
fprintf(stderr,"line %d: %s\n",lino,s);
nerrors++;
}
lookup(comm,operator,lnode,rnode) {
register expr_p p;
for (p=nodes+1;p<lastnode;p++) {
if (p->ex_operator != operator)
continue;
if (!(p->ex_lnode == lnode && p->ex_rnode == rnode ||
comm && p->ex_lnode == rnode && p->ex_rnode == lnode))
continue;
return(p-nodes);
}
if (lastnode >= &nodes[MAXNODES])
yyerror("node table overflow");
lastnode++;
p->ex_operator = operator;
p->ex_lnode = lnode;
p->ex_rnode = rnode;
return(p-nodes);
}
printnodes() {
register expr_p p;
printf("};\n\nshort lastind = %d;\n\nexpr_t enodes[] = {\n",prevind);
for (p=nodes;p<lastnode;p++)
printf("/* %3d */\t%3d,%6u,%6u,\n",
p-nodes,p->ex_operator,p->ex_lnode,p->ex_rnode);
printf("};\n\niarg_t iargs[%d];\n",maxpatlen);
}
initio() {
register i;
printf("#include \"param.h\"\n#include \"types.h\"\n");
printf("#include \"pattern.h\"\n\n");
for(i=0;i<N_EX_OPS;i++) {
nparam[i]=2;
nonumlab[i]=TRUE;
onlyconst[i]=TRUE;
}
nparam[EX_POINTERSIZE] = 0;
nparam[EX_WORDSIZE] = 0;
nparam[EX_CON] = 0;
nparam[EX_ROM] = 0;
nparam[EX_ARG] = 0;
nparam[EX_DEFINED] = 0;
nparam[EX_OR2] = 1;
nparam[EX_AND2] = 1;
nparam[EX_UMINUS] = 1;
nparam[EX_NOT] = 1;
nparam[EX_COMP] = 1;
nparam[EX_NOTREG] = 1;
nonumlab[EX_CMPEQ] = FALSE;
nonumlab[EX_CMPNE] = FALSE;
onlyconst[EX_CMPEQ] = FALSE;
onlyconst[EX_CMPNE] = FALSE;
onlyconst[EX_CMPLE] = FALSE;
onlyconst[EX_CMPLT] = FALSE;
onlyconst[EX_CMPGE] = FALSE;
onlyconst[EX_CMPGT] = FALSE;
onlyconst[EX_PLUS] = FALSE;
onlyconst[EX_MINUS] = FALSE;
printf("byte nparam[] = {");
for (i=0;i<N_EX_OPS;i++) printf("%d,",nparam[i]);
printf("};\nbool nonumlab[] = {");
for (i=0;i<N_EX_OPS;i++) printf("%d,",nonumlab[i]);
printf("};\nbool onlyconst[] = {");
for (i=0;i<N_EX_OPS;i++) printf("%d,",onlyconst[i]);
printf("};\n\nbyte pattern[] = { 0\n");
curind = 1;
}
outbyte(b) {
printf(",%3d",b);
curind++;
}
outshort(s) {
outbyte(s&0377);
outbyte((s>>8)&0377);
}
out(w) {
if (w<255) {
outbyte(w);
} else {
outbyte(255);
outshort(w);
}
}
#include "scan.c"

View File

@@ -1,12 +0,0 @@
/* $Header$ */
/* #define DIAGOPT /* if defined diagnostics are produced */
#ifdef DIAGOPT
#define OPTIM(x) optim(x)
#define O_UNREACH 1001
#define O_BRALAB 1002
#define O_LINLNI 1003
#define O_LINGONE 1004
#else
#define OPTIM(x) /* NOTHING */
#endif

View File

@@ -1,15 +0,0 @@
/* $Header$ */
#define LONGOFF /* if defined long offsets are used */
#define TRUE 1
#define FALSE 0
#define MAXROM 3
#define op_lab (sp_lmnem+1)
#define op_last op_lab
#define ps_sym (sp_lpseu+1)
#define ps_last ps_sym
#define BMASK 0377

View File

@@ -1,126 +0,0 @@
/* $Header$ */
/*
* pattern contains the optimization patterns in an apparently
* unordered fashion. All patterns follow each other unaligned.
* Each pattern looks as follows:
* Byte 0: high byte of hash value associated with this pattern.
* Byte 1-2: index of next pattern with same low byte of hash value.
* Byte 3- : pattern and replacement.
* First comes the pattern length
* then the pattern opcodes,
* then a boolean expression,
* then the one-byte replacement length
* then the intermixed pattern opcodes and operands or
* 0 followed by the one-byte special optimization expression.
* If the DIAGOPT option is set, the optimization is followed
* by the line number in the tables.
*/
/* #define ALLOWSPECIAL /* Special optimizations allowed */
#define PO_HASH 0
#define PO_NEXT 1
#define PO_MATCH 3
struct exprnode {
short ex_operator;
short ex_lnode;
short ex_rnode;
};
typedef struct exprnode expr_t;
typedef struct exprnode *expr_p;
/*
* contents of .ex_operator
*/
#define EX_CON 0
#define EX_ARG 1
#define EX_CMPEQ 2
#define EX_CMPNE 3
#define EX_CMPGT 4
#define EX_CMPGE 5
#define EX_CMPLT 6
#define EX_CMPLE 7
#define EX_OR2 8
#define EX_AND2 9
#define EX_OR1 10
#define EX_XOR1 11
#define EX_AND1 12
#define EX_PLUS 13
#define EX_MINUS 14
#define EX_TIMES 15
#define EX_DIVIDE 16
#define EX_MOD 17
#define EX_LSHIFT 18
#define EX_RSHIFT 19
#define EX_UMINUS 20
#define EX_NOT 21
#define EX_COMP 22
#define EX_ROM 23
#define EX_NOTREG 24
#define EX_POINTERSIZE 25
#define EX_WORDSIZE 26
#define EX_DEFINED 27
#define EX_SAMESIGN 28
#define EX_SFIT 29
#define EX_UFIT 30
#define EX_ROTATE 31
#define N_EX_OPS 32 /* must be one higher then previous */
/*
* Definition of special opcodes used in patterns
*/
#define op_pfirst op_LLP
#define op_LLP (op_last+1)
#define op_LEP (op_last+2)
#define op_SLP (op_last+3)
#define op_SEP (op_last+4)
#define op_plast op_SEP
/*
* Definition of the structure in which instruction operands
* are kept during pattern matching.
*/
typedef struct eval eval_t;
typedef struct eval *eval_p;
struct eval {
short e_typ;
union {
offset e_con;
num_p e_np;
} e_v;
};
/*
* contents of .e_typ
*/
#define EV_UNDEF 0
#define EV_CONST 1
#define EV_NUMLAB 2
#define EV_FRAG 3 /* and all higher numbers */
typedef struct iarg iarg_t;
typedef struct iarg *iarg_p;
struct iarg {
eval_t ia_ev;
sym_p ia_sp;
};
/*
* The next extern declarations refer to data generated by mktab
*/
extern byte pattern[];
extern short lastind;
extern iarg_t iargs[];
extern byte nparam[];
extern bool nonumlab[];
extern bool onlyconst[];
extern expr_t enodes[];

View File

@@ -1,475 +0,0 @@
/* $Header$ */
loc adi loc sbi $2==w && $4==w: loc $1-$3 adi w
ldc adi ldc sbi $2==2*w && $4==2*w: ldc $1-$3 adi 2*w
loc adi loc adi $2==w && $4==w: loc $1+$3 adi w
ldc adi ldc adi $2==2*w && $4==2*w: ldc $1+$3 adi 2*w
adp $1==0:
adp adp : adp $1+$2
adp lof : lof $1+$2
adp ldf : ldf $1+$2
adp loi $1!=0 && $2==w: lof $1
adp loi $1!=0 && $2==2*w: ldf $1
adp stf : stf $1+$2
adp sdf : sdf $1+$2
adp sti $1!=0 && $2==w: stf $1
adp sti $1!=0 && $2==2*w: sdf $1
asp $1==0:
asp asp : asp $1+$2
blm $1==0 : asp 2*p
cmi zeq $1==w: beq $2
cmi zge $1==w: bge $2
cmi zgt $1==w: bgt $2
cmi zle $1==w: ble $2
cmi zlt $1==w: blt $2
cmi zne $1==w: bne $2
dvi ngi $1==$2: ngi $1 dvi $1
lae adp : lae $1+$2
lae blm $2==w: loi w ste $1
lae blm $2==2*w: loi 2*w sde $1
lae ldf : lde $1+$2
lae lof : loe $1+$2
lae loi $2==w: loe $1
lae loi $2==2*w: lde $1
#ifdef INT
lae loi loe $3==$1-w && $2%w==0: lae $3 loi $2+w
lae loi lde $3==$1-2*w && $2%w==0: lae $3 loi $2+2*w
lae loi lae loi $1==$3+$4 && $2%w==0 && $4%w==0: lae $3 loi $2+$4
lae sti ste $3==$1+$2: lae $1 sti $2+w
lae sti sde $3==$1+$2: lae $1 sti $2+2*w
lae sti loc ste $4==$1-w: loc $3 lae $4 sti $2+w
lae sti lol ste $4==$1-w: lol $3 lae $4 sti $2+w
#endif
lae lae blm loe ste $4==$1+$3 && $5==$2+$3: lae $1 lae $2 blm $3+w
lae lae blm lde sde $4==$1+$3 && $5==$2+$3: lae $1 lae $2 blm $3+2*w
lae lae blm lae lae blm $4==$1+$3 && $5==$2+$3: lae $1 lae $2 blm $3+$6
lae lal blm lae lal blm $4==$1+$3 && $5==$2+$3 && samesign($2,$5):
lae $1 lal $2 blm $3+$6
lal lae blm lal lae blm $4==$1+$3 && $5==$2+$3 && samesign($1,$4):
lal $1 lae $2 blm $3+$6
lal lal blm lal lal blm $4==$1+$3 && $5==$2+$3 && samesign($1,$4) && samesign($2,$5):
lal $1 lal $2 blm $3+$6
lal lal sbs $3==w && samesign($1,$2): loc $1-$2
lae sdf : sde $1+$2
lae stf : ste $1+$2
lae sti $2==w: ste $1
lae sti $2==2*w: sde $1
lal adp samesign($1,$1+$2): lal $1+$2
lal blm $2==w: loi w stl $1
lal blm $2==2*w: loi 2*w sdl $1
#ifdef INT
lal sti loc stl notreg($4) && $4==$1-w && samesign($1,$4):
loc $3 lal $4 sti $2+w
lal sti loe stl notreg($4) && $4==$1-w && samesign($1,$4):
loe $3 lal $4 sti $2+w
#endif
lal ldf samesign($1,$1+$2): ldl $1+$2
lal lof samesign($1,$1+$2): lol $1+$2
lal loi $2==w: lol $1
lal loi $2==2*w: ldl $1
#ifdef INT
lal loi lol notreg($3) && $3==$1-w && samesign($1,$3) && $2%w==0:
lal $3 loi $2+w
lal loi ldl notreg($3) && $3==$1-2*w && samesign($1,$3) && $2%w==0:
lal $3 loi $2+2*w
lal loi lal loi $1==$3+$4 && samesign($1,$3) && $2%w==0 && $4%w==0:
lal $3 loi $2+$4
lal sti stl notreg($3) && $3==$1+$2 && samesign($1,$3): lal $1 sti $2+w
lal sti sdl notreg($3) && $3==$1+$2 && samesign($1,$3): lal $1 sti $2+2*w
#endif
lal sdf samesign($1,$1+$2): sdl $1+$2
lal stf samesign($1,$1+$2): stl $1+$2
lal sti $2==w: stl $1
lal sti $2==2*w: sdl $1
#ifdef INT
lde lde $2==$1-2*w: lae $2 loi 4*w
lde loe $2==$1-w: lae $2 loi 3*w
#endif
lde sde $2==$1:
lde sde lde sde $3==$1+2*w && $4==$2+2*w: lae $1 lae $2 blm 4*w
#ifdef INT
ldl ldl $2==$1-2*w && notreg($1) && notreg($2) && samesign($1,$2):
lal $2 loi 4*w
ldl lol $2==$1-w && notreg($1) && notreg($2) && samesign($1,$2):
lal $2 loi 3*w
#endif
ldl sdl $1==$2:
lxa loi lxa sti $3==$1 && $4==$2:
lxa lof lxa stf $3==$1 && $4==$2:
lxa ldf lxa sdf $3==$1 && $4==$2:
lxa stf lxa lof $3==$1 && $4==$2: dup w lxa $1 stf $2
lxa sdf lxa ldf $3==$1 && $4==$2: dup 2*w lxa $1 sdf $2
lxl lof lxl stf $3==$1 && $4==$2:
lxl ldf lxl sdf $3==$1 && $4==$2:
lxl stf lxl lof $3==$1 && $4==$2: dup w lxl $1 stf $2
lxl sdf lxl ldf $3==$1 && $4==$2: dup 2*w lxl $1 sdf $2
lxa sti lxa loi $3==$1 && $4==$2 && $2%w==0: dup $2 lxa $1 sti $2
loc adi $1==-1 && $2==w: dec
loc dec sfit($1-1,8*w) : loc $1-1
loc bgt $1==-1: zge $2
loc ble $1==-1: zlt $2
loc dvi $1==-1 && $2==w: ngi w
ldc dvi $1==-1 && $2==2*w: ngi 2*w
loc loe adi $1==-1 && $3==w: loe $2 dec
loc loe mli $1==-1 && $3==w: loe $2 ngi w
loc lol adi $1==-1 && $3==w: lol $2 dec
loc mli $1==-1 && $2==w: ngi w
ldc mli $1==-1 && $2==2*w: ngi 2*w
loc sbi $1==-1 && $2==w: inc
loc inc sfit($1+1,8*w) : loc $1+1
loc adi $1==0 && $2==w:
ldc adi $1==0 && $2==2*w:
zer adi $1==$2:
loc beq $1==0: zeq $2
loc bge $1==0: zge $2
loc bgt $1==0: zgt $2
loc ble $1==0: zle $2
loc blt $1==0: zlt $2
loc bne $1==0: zne $2
loc cmi teq $1==0 && $2==w: teq
loc cmi tge $1==0 && $2==w: tge
loc cmi tgt $1==0 && $2==w: tgt
loc cmi tle $1==0 && $2==w: tle
loc cmi tlt $1==0 && $2==w: tlt
loc cmi tne $1==0 && $2==w: tne
loc ior $1==0 && $2==w:
ldc ior $1==0 && $2==2*w:
zer ior $1==$2:
loc ste $1==0: zre $2
loc stl $1==0: zrl $2
loc sbi $1==0 && $2==w:
ldc sbi $1==0 && $2==2*w:
zer sbi $1==$2:
loc xor $1==0 && $2==w:
ldc xor $1==0 && $2==2*w:
zer xor $1==$2:
loc adi $1==1 && $2==w: inc
loc bge $1==1: zgt $2
loc blt $1==1: zle $2
loc dvi $1==1 && $2==w:
ldc dvi $1==1 && $2==2*w:
loc loe adi $1==1 && $3==w: loe $2 inc
loc loe mli $1==1 && $3==w: loe $2
loc lol adi $1==1 && $3==w: lol $2 inc
loc lol mli $1==1 && $3==w: lol $2
loc mli $1==1 && $2==w:
loc sbi $1==1 && $2==w: dec
loc loe mli $3==w: loe $2 loc $1 mli w
loc lol mli $3==w: lol $2 loc $1 mli w
ldc lde mli $3==2*w: lde $2 ldc $1 mli 2*w
ldc lde adi $3==2*w: lde $2 ldc $1 adi 2*w
ldc ldl mli $3==2*w: ldl $2 ldc $1 mli 2*w
ldc ldl adi $3==2*w: ldl $2 ldc $1 adi 2*w
loc mli $1==2 && $2==w: loc 1 sli w
loc mli $1==4 && $2==w: loc 2 sli w
loc mli $1==8 && $2==w: loc 3 sli w
loc mli $1==16 && $2==w: loc 4 sli w
loc mli $1==32 && $2==w: loc 5 sli w
loc mli $1==64 && $2==w: loc 6 sli w
loc mli $1==128 && $2==w: loc 7 sli w
loc mli $1==256 && $2==w: loc 8 sli w
loc adi !defined($2): adi $1
loc sbi !defined($2): sbi $1
loc mli !defined($2): mli $1
loc dvi !defined($2): dvi $1
loc rmi !defined($2): rmi $1
loc ngi !defined($2): ngi $1
loc sli !defined($2): sli $1
loc sri !defined($2): sri $1
loc adu !defined($2): adu $1
loc sbu !defined($2): sbu $1
loc mlu !defined($2): mlu $1
loc dvu !defined($2): dvu $1
loc rmu !defined($2): rmu $1
loc slu !defined($2): slu $1
loc sru !defined($2): sru $1
loc adf !defined($2): adf $1
loc sbf !defined($2): sbf $1
loc mlf !defined($2): mlf $1
loc dvf !defined($2): dvf $1
loc ngf !defined($2): ngf $1
loc fif !defined($2): fif $1
loc fef !defined($2): fef $1
loc zer !defined($2): zer $1
loc zrf !defined($2): zrf $1
loc los $2==w: loi $1
loc sts $2==w: sti $1
loc ads $2==w: adp $1
loc ass $2==w: asp $1
loc bls $2==w: blm $1
loc dus $2==w: dup $1
loc loc cii $1==$2:
loc loc cuu $1==$2:
loc loc cff $1==$2:
loc and !defined($2): and $1
loc ior !defined($2): ior $1
loc xor !defined($2): xor $1
loc com !defined($2): com $1
loc rol !defined($2): rol $1
loc rol $1==0:
loc ror !defined($2): ror $1
loc ror $1==0:
loc inn !defined($2): inn $1
loc set !defined($2): set $1
loc cmi !defined($2): cmi $1
loc cmu !defined($2): cmu $1
loc cmf !defined($2): cmf $1
loe dec ste $1==$3: dee $1
loe inc ste $1==$3: ine $1
loe loc mli $2==0 && $3==w: loc 0
#ifdef INT
loe loe $2==$1-w: lde $2
loe loe beq $2==$1+w: lde $1 beq $3
loe loe bge $2==$1+w: lde $1 ble $3
loe loe bgt $2==$1+w: lde $1 blt $3
loe loe ble $2==$1+w: lde $1 bge $3
loe loe blt $2==$1+w: lde $1 bgt $3
loe loe bne $2==$1+w: lde $1 bne $3
loe loe cmi $2==$1+w && $3==w: lde $1 cmi w ngi w
#endif
ngi teq $1==w: teq
ngi tge $1==w: tle
ngi tgt $1==w: tlt
ngi tle $1==w: tge
ngi tlt $1==w: tgt
ngi tne $1==w: tne
#ifdef INT
loe loe mli $2==$1+w && $3==w: lde $1 mli w
loe loe adi $2==$1+w && $3==w: lde $1 adi w
loe loe $1==$2: loe $1 dup w
#endif
loe ste $1==$2:
LLP blm $2==w: loi w sil $1
lol dec stl $1==$3: del $1
lol inc stl $1==$3: inl $1
lol loc mli $2==0 && $3==w: loc 0
LLP loi $2==w: lil $1
#ifdef INT
lol lol $2==$1-w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $2
lol lol beq $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 beq $3
lol lol bge $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 ble $3
lol lol bgt $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 blt $3
lol lol ble $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 bge $3
lol lol blt $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 bgt $3
lol lol bne $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 bne $3
lol lol cmi $3==w && $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 cmi w ngi w
lol lol mli $3==w && $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 mli w
lol lol adi $3==w && $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2):
ldl $1 adi w
lol lol $1==$2: lol $1 dup w
#endif
lol stl $1==$2:
LLP sti $2==w: sil $1
mli ngi $1==$2: ngi $1 mli $1
ngi adi $1==$2: sbi $1
ngf adf $1==$2: sbf $1
ngi sbi $1==$2: adi $1
ngf sbf $1==$2: adf $1
ngi ngi $1==$2:
ngf ngf $1==$2:
#ifdef INT
sde sde $2==$1+2*w: lae $1 sti 4*w
sde ste $2==$1+2*w: lae $1 sti 3*w
sde loc ste $3==$1-w: loc $2 lae $3 sti 3*w
sde lol ste $3==$1-w: lol $2 lae $3 sti 3*w
sde lde $1==$2: dup 2*w sde $1
#endif
sdf $1==0: sti 2*w
#ifdef INT
sdl sdl $2==$1+2*w && notreg($1) && notreg($2) && samesign($1,$2):
lal $1 sti 4*w
sdl stl $2==$1+2*w && notreg($1) && notreg($2) && samesign($1,$2):
lal $1 sti 3*w
sdl loc stl $3==$1-w && notreg($1) && notreg($3) && samesign($1,$3):
loc $2 lal $3 sti 3*w
sdl loe stl $3==$1-w && notreg($1) && notreg($3) && samesign($1,$3):
loe $2 lal $3 sti 3*w
sdl ldl $1==$2: dup 2*w sdl $1
ste loe $1==$2: dup w ste $1
ste ste $2==$1-w: sde $2
ste loc ste $3==$1-w: loc $2 sde $3
ste lol ste $3==$1-w: lol $2 sde $3
stl lol $1==$2: dup w stl $1
#endif
stf $1==0: sti w
sdl ldl ret $1==$2 && $3==2*w: ret 2*w
#ifdef INT
stl stl $2==$1+w && notreg($1) && notreg($2) && samesign($1,$2): sdl $1
stl loc stl $3==$1-w && notreg($1) && notreg($3) && samesign($1,$3):
loc $2 sdl $3
stl loe stl $3==$1-w && notreg($1) && notreg($3) && samesign($1,$3):
loe $2 sdl $3
#endif
stl lol ret $1==$2 && $3==w: ret w
lal sti lal loi ret $1==$3 && $2==$4 && $2==$5: ret $2
loc sbi loc sbi $2==w && $4==w: loc $1+$3 sbi w
ldc sbi ldc sbi $2==2*w && $4==2*w: ldc $1+$3 sbi 2*w
loc sbi loc adi $2==w && $4==w: loc $1-$3 sbi w
ldc sbi ldc adi $2==2*w && $4==2*w: ldc $1-$3 sbi 2*w
teq teq : tne
teq tne : teq
teq zne : zeq $2
teq zeq : zne $2
tge teq : tlt
tge tne : tge
tge zeq : zlt $2
tge zne : zge $2
tgt teq : tle
tgt tne : tgt
tgt zeq : zle $2
tgt zne : zgt $2
tle teq : tgt
tle tne : tle
tle zeq : zgt $2
tle zne : zle $2
tlt teq : tge
tlt tne : tlt
tlt zeq : zge $2
tlt zne : zlt $2
tne teq : teq
tne tne : tne
tne zeq : zeq $2
tne zne : zne $2
#ifdef INT
loc loc loc $1==0 && $2==0 && $3==0 : zer 6
zer loc defined($1) && $2==0: zer $1+w
#endif
loi loc and $1==1 && $3==w && ($2&255)==255: loi 1
loi loc loc cii $1<w && $2==w: loi $1 loc $2 loc $3 cuu
cmp teq : cms p teq
cmp tne : cms p tne
cmu teq defined($1): cms $1 teq
cmu tne defined($1): cms $1 tne
cms zeq $1==w: beq $2
cms zne $1==w: bne $2
lol lae aar adp $3==w: adp $4 lol $1 lae $2 aar w
loe lae aar adp $3==w: adp $4 loe $1 lae $2 aar w
cmi zeq defined($1): cms $1 zeq $2
cmi zne defined($1): cms $1 zne $2
loe inc dup ste $1==$4 && $3==w: ine $1 loe $1
loe dec dup ste $1==$4 && $3==w: dee $1 loe $1
lol inc dup stl $1==$4 && $3==w: inl $1 lol $1
lol dec dup stl $1==$4 && $3==w: del $1 lol $1
adp dup SEP adp $1==-$4 && $2==p: dup p adp $1 SEP $3
adp dup SLP adp $1==-$4 && $2==p: dup p adp $1 SLP $3
inc dup ste dec $2==w: dup w inc ste $3
inc dup stl dec $2==w: dup w inc stl $3
zeq bra lab $1==$3: zne $2 lab $1
zge bra lab $1==$3: zlt $2 lab $1
zgt bra lab $1==$3: zle $2 lab $1
zlt bra lab $1==$3: zge $2 lab $1
zle bra lab $1==$3: zgt $2 lab $1
zne bra lab $1==$3: zeq $2 lab $1
beq bra lab $1==$3: bne $2 lab $1
bge bra lab $1==$3: blt $2 lab $1
bgt bra lab $1==$3: ble $2 lab $1
blt bra lab $1==$3: bge $2 lab $1
ble bra lab $1==$3: bgt $2 lab $1
bne bra lab $1==$3: beq $2 lab $1
lin lin : lin $2
lin lab lin : lab $2 lin $3
lin ret : ret $2
lin bra : bra $2
dup SLP loi $1==p && $3==w: SLP $2 lil $2
dup SLP sti $1==p && $3==w: SLP $2 sil $2
loc cms $1==0 && $2==w: tne
zer $1==w: loc 0
loc loc adi $3==w && sfit($1+$2,8*w) : loc $1+$2
loc loc sbi $3==w && sfit($1-$2,8*w) : loc $1-$2
loc loc mli $3==w && sfit($1*$2,8*w) : loc $1*$2
loc loc dvi $3==w && $2!=0 : loc $1/$2
loc loc and $3==w : loc $1&$2
loc loc ior $3==w : loc $1|$2
loc loc ior $1==0 && $2==0 && $3==2*w :
loc loc xor $3==w : loc $1^$2
loc loc xor $1==0 && $2==0 && $3==2*w :
loc loc rol $3==w : loc rotate($1,$2)
loc loc ror $3==w : loc rotate($1,8*w-$2)
loc ngi $2==w && sfit(-$1,8*w) : loc -$1
loc com $2==w : loc ~$1
ldc ngi $2==2*w : ldc -$1
loc lae aar $3==w && $1>=rom(2,0) && $1 <= rom(2,0)+rom(2,1) :
adp ($1-rom(2,0))*rom(2,2)
loc lae lar $3==w && $1>=rom(2,0) && $1 <= rom(2,0)+rom(2,1) :
adp ($1-rom(2,0))*rom(2,2) loi rom(2,2)
loc lae sar $3==w && $1>=rom(2,0) && $1 <= rom(2,0)+rom(2,1) :
adp ($1-rom(2,0))*rom(2,2) sti rom(2,2)
loc teq : loc $1==0
loc tne : loc $1!=0
loc tge : loc $1>=0
loc tle : loc $1<=0
loc tgt : loc $1>0
loc tlt : loc $1<0
loc zeq $1==0 : bra $2
loc zeq :
loc zne $1!=0 : bra $2
loc zne :
loc zge $1>=0 : bra $2
loc zge :
loc zle $1<=0 : bra $2
loc zle :
loc zgt $1>0 : bra $2
loc zgt :
loc zlt $1<0 : bra $2
loc zlt :
loc loc beq $1==$2 : bra $3
loc loc beq :
loc loc bne $1!=$2 : bra $3
loc loc bne :
loc loc bge $1>=$2 : bra $3
loc loc bge :
loc loc ble $1<=$2 : bra $3
loc loc ble :
loc loc bgt $1>$2 : bra $3
loc loc bgt :
loc loc blt $1<$2 : bra $3
loc loc blt :
lae loi lal sti $2==$4 && $2>4*w : lae $1 lal $3 blm $2
lal loi lae sti $2==$4 && $2>4*w : lal $1 lae $3 blm $2
lal loi lal sti $2==$4 && $2>4*w && ( $3<=$1-$2 || $3>=$1+$2 ) :
lal $1 lal $3 blm $2
lae loi lae sti $2==$4 && $2>4*w && ( !defined($1==$3) || $3<=$1-$2 || $3>=$1+$2 ) :
lae $1 lae $3 blm $2
loc loc loc cif $1==0 && $2==w : zrf $3
loc loc loc ciu $1>=0 && $2==w && $3==2*w : ldc $1
loc loc loc cii $2==w && $3==2*w : ldc $1
loi loc inn $1==$3 && $2>=0 && $2<$1*8 :
lof ($2/(8*w))*w loc $2&(8*w-1) inn w
ldl loc inn $3==2*w && $2>=0 && $2<16*w :
lol $1+($2/(8*w))*w loc $2&(8*w-1) inn w
lde loc inn $3==2*w && $2>=0 && $2<16*w :
loe $1+($2/(8*w))*w loc $2&(8*w-1) inn w
ldf loc inn $3==2*w && $2>=0 && $2<16*w :
lof $1+($2/(8*w))*w loc $2&(8*w-1) inn w
loc inn $1<0 || $1>=8*$2 : asp $2 loc 0
lol loc adi stl $3==w && $1==$4 : loc $2 lol $1 adi w stl $4
lol loe adi stl $3==w && $1==$4 : loe $2 lol $1 adi w stl $4
lol lol adi stl $3==w && $1==$4 && $1!=$2 : lol $2 lol $1 adi w stl $4
loe loc adi ste $3==w && $1==$4 : loc $2 loe $1 adi w ste $4
loe loe adi ste $3==w && $1==$4 && $1!=$2 : loe $2 loe $1 adi w ste $4
loe lol adi ste $3==w && $1==$4 : lol $2 loe $1 adi w ste $4
lol loc ior stl $3==w && $1==$4 : loc $2 lol $1 ior w stl $4
lol loe ior stl $3==w && $1==$4 : loe $2 lol $1 ior w stl $4
lol lol ior stl $3==w && $1==$4 && $1!=$2 : lol $2 lol $1 ior w stl $4
loe loc ior ste $3==w && $1==$4 : loc $2 loe $1 ior w ste $4
loe loe ior ste $3==w && $1==$4 && $1!=$2 : loe $2 loe $1 ior w ste $4
loe lol ior ste $3==w && $1==$4 : lol $2 loe $1 ior w ste $4
lol loc and stl $3==w && $1==$4 : loc $2 lol $1 and w stl $4
lol loe and stl $3==w && $1==$4 : loe $2 lol $1 and w stl $4
lol lol and stl $3==w && $1==$4 && $1!=$2 : lol $2 lol $1 and w stl $4
loe loc and ste $3==w && $1==$4 : loc $2 loe $1 and w ste $4
loe loe and ste $3==w && $1==$4 && $1!=$2 : loe $2 loe $1 and w ste $4
loe lol and ste $3==w && $1==$4 : lol $2 loe $1 and w ste $4
loi asp $1==$2 : asp p
lal loi loc loc loc loc ior $2==4*w && $7==4*w && ($3==0)+($4==0)+($5==0)+($6==0)>2 :
lol $1+3*w loc $3 ior w lol $1+2*w loc $4 ior w lol $1+w loc $5 ior w lol $1 loc $6 ior w
loc dup stl loc dup stl $2==2 && $5==2:
loc $1 stl $3 loc $4 stl $6 loc $1 loc $4

View File

@@ -1,652 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "assert.h"
#include "line.h"
#include "lookup.h"
#include "proinf.h"
#include "alloc.h"
#include "pattern.h"
#include "../../h/em_spec.h"
#include "../../h/em_mnem.h"
#include "optim.h"
#include "ext.h"
/*
* (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
*
* Author: Hans van Staveren
*/
/* #define CHK_HASH /* print numbers patterns are hashed to */
#ifdef CHK_HASH
#include <stdio.h>
#endif
#define ILLHASH 0177777
short pathash[256]; /* table of indices into pattern[] */
int opind = 0; /* second index of next matrix */
byte transl[op_plast-op_pfirst+1][3] = {
/* LLP */ { op_LLP, op_lol, op_ldl },
/* LEP */ { op_LEP, op_loe, op_lde },
/* SLP */ { op_SLP, op_stl, op_sdl },
/* SEP */ { op_SEP, op_ste, op_sde }
};
opcheck(bp) register byte *bp; {
if (((*bp)&BMASK) >= op_pfirst)
*bp = transl[((*bp)&BMASK)-op_pfirst][opind];
}
/*
* The hashing method used is believed to be reasonably efficient.
* A minor speed improvement could be obtained by keeping a boolean
* array telling which opcode has any patterns starting with it.
* Currently only about one third of the opcodes actually have a
* pattern starting with it, but they are the most common ones.
* Estimated improvement possible: about 2%
*/
hashpatterns() {
short index;
register byte *bp,*tp;
register short i;
unsigned short hashvalue;
byte *save;
int patlen;
if (pointersize == wordsize)
opind=1;
else if (pointersize == 2*wordsize)
opind=2;
index = lastind; /* set by mktab */
while (index != 0) {
bp = &pattern[index];
tp = &bp[PO_MATCH];
i = *tp++&BMASK;
if (i==BMASK) {
i = *tp++&BMASK;
i |= (*tp++&BMASK)<<8;
}
save = tp;
patlen = i;
while (i--)
opcheck(tp++);
if ((*tp++&BMASK)==BMASK)
tp += 2;
i = *tp++&BMASK;
if (i==BMASK) {
i = *tp++&BMASK;
i |= (*tp++&BMASK)<<8;
}
while (i--) {
opcheck(tp++);
if ((*tp++&BMASK)==BMASK)
tp += 2;
}
/*
* Now the special opcodes are filled
* in properly, we can hash the pattern
*/
hashvalue = 0;
tp = save;
switch(patlen) {
default: /* 3 or more */
hashvalue = (hashvalue<<4)^(*tp++&BMASK);
case 2:
hashvalue = (hashvalue<<4)^(*tp++&BMASK);
case 1:
hashvalue = (hashvalue<<4)^(*tp++&BMASK);
}
assert(hashvalue!= ILLHASH);
i=index;
index = (bp[PO_NEXT]&BMASK)|(bp[PO_NEXT+1]<<8);
bp[PO_HASH] = hashvalue>>8;
hashvalue &= BMASK;
bp[PO_NEXT] = pathash[hashvalue]&BMASK;
bp[PO_NEXT+1] = pathash[hashvalue]>>8;
pathash[hashvalue] = i;
#ifdef CHK_HASH
fprintf(stderr,"%d\n",hashvalue);
#endif
}
}
peephole() {
static bool phashed = FALSE;
if (!phashed) {
hashpatterns();
phashed=TRUE;
}
optimize();
}
optimize() {
register num_p *npp,np;
register instr;
basicblock(&instrs);
for (npp=curpro.numhash;npp< &curpro.numhash[NNUMHASH]; npp++)
for (np = *npp; np != (num_p) 0; np=np->n_next) {
if(np->n_line->l_next == (line_p) 0)
continue;
instr = np->n_line->l_next->l_instr&BMASK;
if (instr == op_lab || instr == op_bra)
np->n_repl = np->n_line->l_next->l_a.la_np;
else
basicblock(&np->n_line->l_next);
}
}
offset oabs(off) offset off; {
return(off >= 0 ? off : -off);
}
line_p repline(ev,patlen) eval_t ev; {
register line_p lp;
register iarg_p iap;
register sym_p sp;
offset diff,newdiff;
assert(ev.e_typ != EV_UNDEF);
switch(ev.e_typ) {
case EV_CONST:
if ((short) ev.e_v.e_con == ev.e_v.e_con) {
if (CANMINI((short) ev.e_v.e_con))
lp = newline((short) (ev.e_v.e_con)+Z_OPMINI);
else {
lp = newline(OPSHORT);
lp->l_a.la_short = (short) ev.e_v.e_con;
}
} else {
lp = newline(OPOFFSET);
lp->l_a.la_offset = ev.e_v.e_con;
}
return(lp);
case EV_NUMLAB:
lp = newline(OPNUMLAB);
lp->l_a.la_np = ev.e_v.e_np;
return(lp);
default: /* fragment + offset */
/*
* There is a slight problem here, because we have to
* map fragment+offset to symbol+offset.
* Fortunately the fragment we have must be the fragment
* of one of the symbols in the matchpattern.
* So a short search should do the job.
*/
sp = (sym_p) 0;
for (iap= &iargs[patlen-1]; iap >= iargs; iap--)
if (iap->ia_ev.e_typ == ev.e_typ) {
/*
* Although lint complains, diff is not used
* before set.
*
* The proof is left as an exercise to the
* reader.
*/
newdiff = oabs(iap->ia_sp->s_value-ev.e_v.e_con);
if (sp==(sym_p) 0 || newdiff < diff) {
sp = iap->ia_sp;
diff = newdiff;
}
}
assert(sp != (sym_p) 0);
if (diff == 0) {
lp = newline(OPSYMBOL);
lp->l_a.la_sp = sp;
} else {
diff = ev.e_v.e_con - sp->s_value;
if ((short) diff == diff) {
lp = newline(OPSVAL);
lp->l_a.la_sval.lasv_short = (short) diff;
lp->l_a.la_sval.lasv_sp = sp;
} else {
lp = newline(OPLVAL);
lp->l_a.la_lval.lalv_offset = diff;
lp->l_a.la_lval.lalv_sp = sp;
}
}
return(lp);
}
}
offset rotate(w,amount) offset w,amount; {
offset highmask,lowmask;
#ifndef LONGOFF
assert(wordsize<=4);
#endif
highmask = (offset)(-1) << amount;
lowmask = ~highmask;
if (wordsize != 4)
highmask &= wordsize==2 ? 0xFFFF : 0xFF;
return(((w<<amount)&highmask)|((w>>(8*wordsize-amount))&lowmask));
}
eval_t undefres = { EV_UNDEF };
eval_t compute(pexp) register expr_p pexp; {
eval_t leaf1,leaf2,res;
register i;
register sym_p sp;
offset mask;
switch(nparam[pexp->ex_operator]) {
default:
assert(FALSE);
case 2:
leaf2 = compute(&enodes[pexp->ex_rnode]);
if (leaf2.e_typ == EV_UNDEF ||
nonumlab[pexp->ex_operator] && leaf2.e_typ == EV_NUMLAB ||
onlyconst[pexp->ex_operator] && leaf2.e_typ != EV_CONST)
return(undefres);
case 1:
leaf1 = compute(&enodes[pexp->ex_lnode]);
if (leaf1.e_typ == EV_UNDEF ||
nonumlab[pexp->ex_operator] && leaf1.e_typ == EV_NUMLAB ||
onlyconst[pexp->ex_operator] && leaf1.e_typ != EV_CONST)
return(undefres);
case 0:
break;
}
res.e_typ = EV_CONST;
res.e_v.e_con = 0;
switch(pexp->ex_operator) {
default:
assert(FALSE);
case EX_CON:
res.e_v.e_con = (offset) pexp->ex_lnode;
break;
case EX_ARG:
return(iargs[pexp->ex_lnode - 1].ia_ev);
case EX_CMPEQ:
if (leaf1.e_typ != leaf2.e_typ)
return(undefres);
if (leaf1.e_typ == EV_NUMLAB) {
if (leaf1.e_v.e_np == leaf2.e_v.e_np)
res.e_v.e_con = 1;
break;
}
if (leaf1.e_v.e_con == leaf2.e_v.e_con)
res.e_v.e_con = 1;
break;
case EX_CMPNE:
if (leaf1.e_typ != leaf2.e_typ) {
res.e_v.e_con = 1;
break;
}
if (leaf1.e_typ == EV_NUMLAB) {
if (leaf1.e_v.e_np != leaf2.e_v.e_np)
res.e_v.e_con = 1;
break;
}
if (leaf1.e_v.e_con != leaf2.e_v.e_con)
res.e_v.e_con = 1;
break;
case EX_CMPGT:
if (leaf1.e_typ != leaf2.e_typ)
return(undefres);
res.e_v.e_con = leaf1.e_v.e_con > leaf2.e_v.e_con;
break;
case EX_CMPGE:
if (leaf1.e_typ != leaf2.e_typ)
return(undefres);
res.e_v.e_con = leaf1.e_v.e_con >= leaf2.e_v.e_con;
break;
case EX_CMPLT:
if (leaf1.e_typ != leaf2.e_typ)
return(undefres);
res.e_v.e_con = leaf1.e_v.e_con < leaf2.e_v.e_con;
break;
case EX_CMPLE:
if (leaf1.e_typ != leaf2.e_typ)
return(undefres);
res.e_v.e_con = leaf1.e_v.e_con <= leaf2.e_v.e_con;
break;
case EX_OR2:
if (leaf1.e_v.e_con != 0)
return(leaf1);
leaf2 = compute(&enodes[pexp->ex_rnode]);
if (leaf2.e_typ != EV_CONST)
return(undefres);
return(leaf2);
case EX_AND2:
if (leaf1.e_v.e_con == 0)
return(leaf1);
leaf2 = compute(&enodes[pexp->ex_rnode]);
if (leaf2.e_typ != EV_CONST)
return(undefres);
return(leaf2);
case EX_OR1:
res.e_v.e_con = leaf1.e_v.e_con | leaf2.e_v.e_con;
break;
case EX_XOR1:
res.e_v.e_con = leaf1.e_v.e_con ^ leaf2.e_v.e_con;
break;
case EX_AND1:
res.e_v.e_con = leaf1.e_v.e_con & leaf2.e_v.e_con;
break;
case EX_TIMES:
res.e_v.e_con = leaf1.e_v.e_con * leaf2.e_v.e_con;
break;
case EX_DIVIDE:
res.e_v.e_con = leaf1.e_v.e_con / leaf2.e_v.e_con;
break;
case EX_MOD:
res.e_v.e_con = leaf1.e_v.e_con % leaf2.e_v.e_con;
break;
case EX_LSHIFT:
res.e_v.e_con = leaf1.e_v.e_con << leaf2.e_v.e_con;
break;
case EX_RSHIFT:
res.e_v.e_con = leaf1.e_v.e_con >> leaf2.e_v.e_con;
break;
case EX_UMINUS:
res.e_v.e_con = -leaf1.e_v.e_con;
break;
case EX_NOT:
res.e_v.e_con = !leaf1.e_v.e_con;
break;
case EX_COMP:
res.e_v.e_con = ~leaf1.e_v.e_con;
break;
case EX_PLUS:
if (leaf1.e_typ >= EV_FRAG) {
if (leaf2.e_typ >= EV_FRAG)
return(undefres);
res.e_typ = leaf1.e_typ;
} else
res.e_typ = leaf2.e_typ;
res.e_v.e_con = leaf1.e_v.e_con + leaf2.e_v.e_con;
break;
case EX_MINUS:
if (leaf1.e_typ >= EV_FRAG) {
if (leaf2.e_typ == EV_CONST)
res.e_typ = leaf1.e_typ;
else if (leaf2.e_typ != leaf1.e_typ)
return(undefres);
} else if (leaf2.e_typ >= EV_FRAG)
return(undefres);
res.e_v.e_con = leaf1.e_v.e_con - leaf2.e_v.e_con;
break;
case EX_POINTERSIZE:
res.e_v.e_con = pointersize;
break;
case EX_WORDSIZE:
res.e_v.e_con = wordsize;
break;
case EX_NOTREG:
res.e_v.e_con = !inreg(leaf1.e_v.e_con);
break;
case EX_DEFINED:
leaf1 = compute(&enodes[pexp->ex_lnode]);
res.e_v.e_con = leaf1.e_typ != EV_UNDEF;
break;
case EX_SAMESIGN:
res.e_v.e_con = (leaf1.e_v.e_con ^ leaf2.e_v.e_con) >= 0;
break;
case EX_ROM:
if ((sp = iargs[pexp->ex_lnode - 1].ia_sp) != (sym_p) 0 &&
sp->s_rom != (offset *) 0) {
leaf2 = compute(&enodes[pexp->ex_rnode]);
if (leaf2.e_typ != EV_CONST ||
leaf2.e_v.e_con < 0 ||
leaf2.e_v.e_con >= MAXROM)
return(undefres);
res.e_v.e_con = sp->s_rom[leaf2.e_v.e_con];
break;
} else
return(undefres);
case EX_SFIT:
mask = 0;
for (i=leaf2.e_v.e_con - 1;i < 8*sizeof(offset); i++)
mask |= 1<<i;
res.e_v.e_con = (leaf1.e_v.e_con&mask) == 0 ||
(leaf1.e_v.e_con&mask) == mask;
break;
case EX_UFIT:
mask = 0;
for (i=leaf2.e_v.e_con;i < 8*sizeof(offset); i++)
mask |= 1<<i;
res.e_v.e_con = (leaf1.e_v.e_con&mask) == 0;
break;
case EX_ROTATE:
res.e_v.e_con = rotate(leaf1.e_v.e_con,leaf2.e_v.e_con);
break;
}
return(res);
}
#ifdef ALLOWSPECIAL
extern bool special();
#endif
bool tryrepl(lpp,bp,patlen)
line_p *lpp;
register byte *bp;
int patlen;
{
int rpllen,instr,rplval;
register line_p lp;
line_p replacement,*rlpp,tp;
rpllen = *bp++&BMASK;
if (rpllen == BMASK) {
rpllen = *bp++&BMASK;
rpllen |= (*bp++&BMASK)<<8;
}
#ifdef ALLOWSPECIAL
if (rpllen == 1 && *bp == 0)
return(special(lpp,bp+1,patlen));
#endif
replacement = (line_p) 0;
rlpp = &replacement;
while (rpllen--) {
instr = *bp++&BMASK;
rplval = *bp++&BMASK;
if (rplval == BMASK) {
rplval = (*bp++&BMASK);
rplval |= (*bp++&BMASK)<<8;
}
if (rplval)
lp = repline(compute(&enodes[rplval]),patlen);
else
lp = newline(OPNO);
/*
* One replacement instruction is generated,
* link in list and proceed with the next one.
*/
if (instr == op_lab)
lp->l_a.la_np->n_line = lp;
*rlpp = lp;
rlpp = &lp->l_next;
lp->l_instr = instr;
}
/*
* Replace instructions matched by the created replacement
*/
OPTIM((bp[0]&BMASK)|(bp[1]&BMASK)<<8);
for (lp= *lpp;patlen>0;patlen--,tp=lp,lp=lp->l_next)
;
tp->l_next = (line_p) 0;
*rlpp = lp;
lp = *lpp;
*lpp = replacement;
while ( lp != (line_p) 0 ) {
tp = lp->l_next;
oldline(lp);
lp = tp;
}
return(TRUE);
}
bool trypat(lpp,bp,len)
line_p *lpp;
register byte *bp;
int len;
{
register iarg_p iap;
int i,patlen;
register line_p lp;
eval_t result;
patlen = *bp++&BMASK;
if (patlen == BMASK) {
patlen = *bp++&BMASK;
patlen |= (*bp++&BMASK)<<8;
}
if (len == 3) {
if (patlen<3)
return(FALSE);
} else {
if (patlen != len)
return(FALSE);
}
/*
* Length is ok, now check opcodes
*/
for (i=0,lp= *lpp;i<patlen && lp != (line_p) 0;i++,lp=lp->l_next)
if (lp->l_instr != *bp++)
return(FALSE);
if (i != patlen)
return(FALSE);
/*
* opcodes are also correct, now comes the hard part
*/
for(i=0,lp= *lpp,iap= iargs; i<patlen;i++,iap++,lp=lp->l_next) {
switch(lp->l_optyp) {
case OPNO:
iap->ia_ev.e_typ = EV_UNDEF;
break;
default:
iap->ia_ev.e_typ = EV_CONST;
iap->ia_ev.e_v.e_con = (lp->l_optyp&BMASK)-Z_OPMINI;
break;
case OPSHORT:
iap->ia_ev.e_typ = EV_CONST;
iap->ia_ev.e_v.e_con = lp->l_a.la_short;
break;
#ifdef LONGOFF
case OPOFFSET:
iap->ia_ev.e_typ = EV_CONST;
iap->ia_ev.e_v.e_con = lp->l_a.la_offset;
break;
#endif
case OPNUMLAB:
iap->ia_ev.e_typ = EV_NUMLAB;
iap->ia_ev.e_v.e_np = lp->l_a.la_np;
break;
case OPSYMBOL:
iap->ia_ev.e_typ = lp->l_a.la_sp->s_frag;
iap->ia_sp = lp->l_a.la_sp;
iap->ia_ev.e_v.e_con = lp->l_a.la_sp->s_value;
break;
case OPSVAL:
iap->ia_ev.e_typ = lp->l_a.la_sval.lasv_sp->s_frag;
iap->ia_sp = lp->l_a.la_sval.lasv_sp;
iap->ia_ev.e_v.e_con = lp->l_a.la_sval.lasv_sp->s_value + lp->l_a.la_sval.lasv_short;
break;
#ifdef LONGOFF
case OPLVAL:
iap->ia_ev.e_typ = lp->l_a.la_lval.lalv_sp->s_frag;
iap->ia_sp = lp->l_a.la_lval.lalv_sp;
iap->ia_ev.e_v.e_con = lp->l_a.la_lval.lalv_sp->s_value + lp->l_a.la_lval.lalv_offset;
break;
#endif
}
}
i = *bp++&BMASK;
if ( i==BMASK ) {
i = *bp++&BMASK;
i |= (*bp++&BMASK)<<8;
}
if ( i != 0) {
/* there is a condition */
result = compute(&enodes[i]);
if (result.e_typ != EV_CONST || result.e_v.e_con == 0)
return(FALSE);
}
return(tryrepl(lpp,bp,patlen));
}
basicblock(alpp) line_p *alpp; {
register line_p *lpp,lp;
bool madeopt;
unsigned short hash[3];
line_p *next;
register byte *bp;
int i;
short index;
do { /* make pass over basicblock */
lpp = alpp; madeopt = FALSE;
while ((*lpp) != (line_p) 0 && ((*lpp)->l_instr&BMASK) != op_lab) {
lp = *lpp; next = &lp->l_next;
hash[0] = lp->l_instr&BMASK;
lp=lp->l_next;
if (lp != (line_p) 0) {
hash[1] = (hash[0]<<4)^(lp->l_instr&BMASK);
lp=lp->l_next;
if (lp != (line_p) 0)
hash[2] = (hash[1]<<4)^(lp->l_instr&BMASK);
else
hash[2] = ILLHASH;
} else {
hash[1] = ILLHASH;
hash[2] = ILLHASH;
}
/*
* hashvalues computed. Try for longest pattern first
*/
for (i=2;i>=0;i--) {
index = pathash[hash[i]&BMASK];
while (index != 0) {
bp = &pattern[index];
if((bp[PO_HASH]&BMASK) == (hash[i]>>8))
if(trypat(lpp,&bp[PO_MATCH],i+1)) {
madeopt = TRUE;
next = lpp;
i = 0; /* dirty way of double break */
break;
}
index=(bp[PO_NEXT]&BMASK)|(bp[PO_NEXT+1]<<8);
}
}
lpp = next;
}
} while(madeopt); /* as long as there is progress */
}

View File

@@ -1,185 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "assert.h"
#include "../../h/em_spec.h"
#include "../../h/em_pseu.h"
#include "alloc.h"
#include "line.h"
#include "lookup.h"
#include "proinf.h"
#include "ext.h"
/*
* (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
*
* Author: Hans van Staveren
*/
process() {
if (wordsize == 0 || pointersize == 0)
error("No MES EMX encountered");
backward(); /* reverse and cleanup list */
symknown(); /* symbol scope is now known */
if (!nflag)
symvalue(); /* give symbols value */
if (prodepth != 0) {
if (!nflag) {
checklocs(); /* check definition of locals */
peephole(); /* local optimization */
relabel(); /* relabel local labels */
flow(); /* throw away unreachable code */
}
outpro(); /* generate PRO pseudo */
outregs(); /* generate MES ms_reg pseudos */
}
putlines(pseudos); /* pseudos first */
if (prodepth != 0) {
putlines(instrs); /* instructions next */
outend(); /* generate END pseudo */
cleanlocals(); /* forget instruction labels */
} else if(instrs != (line_p) 0)
error("instructions outside procedure");
#ifdef COREDEBUG
coreverbose();
#endif
}
relabel() {
register num_p *npp,np,tp;
register num_p repl,ttp;
/*
* For each label find its final destination after crossjumping.
* Care has to be taken to prevent a loop in the program to
* cause same in the optimizer.
*/
for (npp = curpro.numhash; npp < &curpro.numhash[NNUMHASH]; npp++)
for (np = *npp; np != (num_p) 0; np = np->n_next) {
assert((np->n_line->l_instr&BMASK) == op_lab
&& np->n_line->l_a.la_np == np);
for(tp=np; (tp->n_flags&(NUMKNOWN|NUMMARK))==0;
tp = tp->n_repl)
tp->n_flags |= NUMMARK;
repl = tp->n_repl;
for(tp=np; tp->n_flags&NUMMARK; tp = ttp) {
ttp = tp->n_repl;
tp->n_repl = repl;
tp->n_flags &= ~ NUMMARK;
tp->n_flags |= NUMKNOWN;
}
}
}
symknown() {
register sym_p *spp,sp;
for (spp = symhash; spp < &symhash[NSYMHASH]; spp++)
for (sp = *spp; sp != (sym_p) 0; sp = sp->s_next)
sp->s_flags |= SYMKNOWN;
}
cleanlocals() {
register num_p *npp,np,tp;
for (npp = curpro.numhash; npp < &curpro.numhash[NNUMHASH]; npp++) {
np = *npp;
while (np != (num_p) 0) {
tp = np->n_next;
oldnum(np);
np = tp;
}
*npp = (num_p) 0;
}
}
checklocs() {
register num_p *npp,np;
for (npp=curpro.numhash; npp < & curpro.numhash[NNUMHASH]; npp++)
for (np = *npp; np != (num_p) 0; np=np->n_next)
if (np->n_line == (line_p) 0)
error("local label %u undefined",
(unsigned) np->n_number);
}
offset align(count,alignment) offset count,alignment; {
assert(alignment==1||alignment==2||alignment==4);
return((count+alignment-1)&~(alignment-1));
}
symvalue() {
register line_p lp;
register sym_p sp;
register arg_p ap;
register argb_p abp;
short curfrag = 0;
offset count;
for (lp=pseudos; lp != (line_p) 0; lp = lp->l_next)
switch(lp->l_instr&BMASK) {
default:
assert(FALSE);
case ps_sym:
sp = lp->l_a.la_sp;
if (sp->s_frag != curfrag) {
count = 0;
curfrag = sp->s_frag;
}
count = align(count,wordsize);
sp->s_value = count;
break;
case ps_bss:
case ps_hol:
/* nothing to do, all bss pseudos are in diff frags */
case ps_mes:
break;
case ps_con:
case ps_rom:
for (ap=lp->l_a.la_arg; ap != (arg_p) 0; ap = ap->a_next)
switch(ap->a_typ) {
default:
assert(FALSE);
case ARGOFF:
count = align(count,wordsize)+wordsize;
break;
case ARGNUM:
case ARGSYM:
case ARGVAL:
count = align(count,wordsize)+pointersize;
break;
case ARGICN:
case ARGUCN:
case ARGFCN:
if (ap->a_a.a_con.ac_length < wordsize)
count = align(count,(offset)ap->a_a.a_con.ac_length);
else
count = align(count,wordsize);
count += ap->a_a.a_con.ac_length;
break;
case ARGSTR:
for (abp = &ap->a_a.a_string; abp != (argb_p) 0;
abp = abp->ab_next)
count += abp->ab_index;
break;
}
}
}

View File

@@ -1,36 +0,0 @@
/* $Header$ */
struct num {
num_p n_next;
unsigned n_number;
unsigned n_jumps;
num_p n_repl;
short n_flags;
line_p n_line;
};
/* contents of .n_flags */
#define NUMDATA 000001
#define NUMREACH 000002
#define NUMKNOWN 000004
#define NUMMARK 000010
#define NUMSCAN 000020
#define NNUMHASH 37
extern num_p numlookup();
struct regs {
reg_p r_next;
offset r_par[4];
};
typedef struct proinf {
offset localbytes;
line_p lastline;
sym_p symbol;
reg_p freg;
bool gtoproc;
num_p numhash[NNUMHASH];
} proinf;
extern proinf curpro;

View File

@@ -1,381 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
#include "assert.h"
#include "../../h/em_spec.h"
#include "../../h/em_pseu.h"
#include "../../h/em_mnem.h"
#include "../../h/em_flag.h"
#include "alloc.h"
#include "line.h"
#include "lookup.h"
#include "proinf.h"
#include "optim.h"
#include "ext.h"
/*
* (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
*
* Author: Hans van Staveren
*/
#define outbyte(b) putc(b,outfile)
putlines(lnp) register line_p lnp; {
register arg_p ap;
line_p temp;
register instr;
short curlin= -2;
short thislin;
while ( lnp != (line_p) 0) {
instr = lnp->l_instr&BMASK;
switch(lnp->l_optyp) {
case OPSYMBOL:
if ((lnp->l_instr&BMASK) == ps_sym)
outdef(lnp->l_a.la_sp);
else
outocc(lnp->l_a.la_sp);
break;
case OPSVAL:
outocc(lnp->l_a.la_sval.lasv_sp);
break;
#ifdef LONGOFF
case OPLVAL:
outocc(lnp->l_a.la_lval.lalv_sp);
break;
#endif
case OPLIST:
ap = lnp->l_a.la_arg;
while (ap != (arg_p) 0) {
switch(ap->a_typ) {
case ARGSYM:
outocc(ap->a_a.a_sp);
break;
case ARGVAL:
outocc(ap->a_a.a_val.av_sp);
break;
}
ap = ap->a_next;
}
break;
}
/*
* global symbols now taken care of
*/
switch(instr) {
case ps_sym:
break;
case op_lni:
if (curlin != -2)
curlin++;
outinst(instr);
break;
case op_lin:
switch(lnp->l_optyp) {
case OPNO:
case OPOFFSET:
case OPNUMLAB:
case OPSYMBOL:
case OPSVAL:
case OPLVAL:
case OPLIST:
outinst(instr);
goto processoperand;
case OPSHORT:
thislin = lnp->l_a.la_short;
break;
default:
thislin = (lnp->l_optyp&BMASK)-Z_OPMINI;
break;
}
if (thislin == curlin && !nflag) {
temp = lnp->l_next;
oldline(lnp);
lnp = temp;
OPTIM(O_LINGONE);
continue;
} else if (thislin == curlin+1 && !nflag) {
instr = op_lni;
outinst(instr);
temp = lnp->l_next;
oldline(lnp);
OPTIM(O_LINLNI);
lnp = newline(OPNO);
lnp->l_next = temp;
lnp->l_instr = instr;
} else {
outinst(instr);
}
curlin = thislin;
break;
case op_lab:
curlin = -2;
break;
default:
if ((em_flag[instr-sp_fmnem]&EM_FLO)==FLO_P)
curlin = -2;
outinst(instr);
}
processoperand:
switch(lnp->l_optyp) {
case OPNO:
if ((em_flag[instr-sp_fmnem]&EM_PAR)!=PAR_NO)
outbyte( (byte) sp_cend) ;
break;
default:
outint((lnp->l_optyp&BMASK)-Z_OPMINI);
break;
case OPSHORT:
outint(lnp->l_a.la_short);
break;
#ifdef LONGOFF
case OPOFFSET:
outoff(lnp->l_a.la_offset);
break;
#endif
case OPNUMLAB:
if (instr == op_lab)
numlab(lnp->l_a.la_np->n_repl);
else if (instr < sp_fpseu) /* plain instruction */
outint((short) lnp->l_a.la_np->n_repl->n_number);
else
outnum(lnp->l_a.la_np->n_repl);
break;
case OPSYMBOL:
outsym(lnp->l_a.la_sp);
break;
case OPSVAL:
outbyte( (byte) sp_doff) ;
outsym(lnp->l_a.la_sval.lasv_sp);
outint(lnp->l_a.la_sval.lasv_short);
break;
#ifdef LONGOFF
case OPLVAL:
outbyte( (byte) sp_doff) ;
outsym(lnp->l_a.la_lval.lalv_sp);
outoff(lnp->l_a.la_lval.lalv_offset);
break;
#endif
case OPLIST:
putargs(lnp->l_a.la_arg);
switch(instr) {
case ps_con:
case ps_rom:
case ps_mes:
outbyte( (byte) sp_cend) ;
}
}
/*
* instruction is output now.
* remove its useless body
*/
temp = lnp->l_next;
oldline(lnp);
lnp = temp;
if (ferror(outfile))
error("write error");
}
}
putargs(ap) register arg_p ap; {
while (ap != (arg_p) 0) {
switch(ap->a_typ) {
default:
assert(FALSE);
case ARGOFF:
outoff(ap->a_a.a_offset);
break;
case ARGNUM:
outnum(ap->a_a.a_np->n_repl);
break;
case ARGSYM:
outsym(ap->a_a.a_sp);
break;
case ARGVAL:
outbyte( (byte) sp_doff) ;
outsym(ap->a_a.a_val.av_sp);
outoff(ap->a_a.a_val.av_offset);
break;
case ARGSTR:
outbyte( (byte) sp_scon) ;
putstr(&ap->a_a.a_string);
break;
case ARGICN:
outbyte( (byte) sp_icon) ;
goto casecon;
case ARGUCN:
outbyte( (byte) sp_ucon) ;
goto casecon;
case ARGFCN:
outbyte( (byte) sp_fcon) ;
casecon:
outint(ap->a_a.a_con.ac_length);
putstr(&ap->a_a.a_con.ac_con);
break;
}
ap = ap->a_next;
}
}
putstr(abp) register argb_p abp; {
register argb_p tbp;
register length;
length = 0;
tbp = abp;
while (tbp!= (argb_p) 0) {
length += tbp->ab_index;
tbp = tbp->ab_next;
}
outint(length);
while (abp != (argb_p) 0) {
for (length=0;length<abp->ab_index;length++)
outbyte( (byte) abp->ab_contents[length] );
abp = abp->ab_next;
}
}
outdef(sp) register sym_p sp; {
/*
* The surrounding If statement is removed to be friendly
* to Backend writers having to deal with assemblers
* not following our conventions.
if ((sp->s_flags&SYMOUT)==0) {
*/
sp->s_flags |= SYMOUT;
if (sp->s_flags&SYMGLOBAL) {
outinst(sp->s_flags&SYMPRO ? ps_exp : ps_exa);
outsym(sp);
}
/*
}
*/
}
outocc(sp) register sym_p sp; {
if ((sp->s_flags&SYMOUT)==0) {
sp->s_flags |= SYMOUT;
if ((sp->s_flags&SYMGLOBAL)==0) {
outinst(sp->s_flags&SYMPRO ? ps_inp : ps_ina);
outsym(sp);
}
}
}
outpro() {
outdef(curpro.symbol);
outinst(ps_pro);
outsym(curpro.symbol);
outoff(curpro.localbytes);
}
outend() {
outinst(ps_end);
outoff(curpro.localbytes);
}
outinst(m) {
outbyte( (byte) m );
}
outoff(off) offset off; {
#ifdef LONGOFF
if ((short) off == off)
#endif
outint((short) off);
#ifdef LONGOFF
else {
outbyte( (byte) sp_cst4) ;
outshort( (short) (off&0177777L) );
outshort( (short) (off>>16) );
}
#endif
}
outint(i) short i; {
if (i>= -sp_zcst0 && i< sp_ncst0-sp_zcst0)
outbyte( (byte) (i+sp_zcst0+sp_fcst0) );
else {
outbyte( (byte) sp_cst2) ;
outshort(i);
}
}
outshort(i) short i; {
outbyte( (byte) (i&BMASK) );
outbyte( (byte) (i>>8) );
}
numlab(np) register num_p np; {
if (np->n_number < sp_nilb0)
outbyte( (byte) (np->n_number + sp_filb0) );
else
outnum(np);
}
outnum(np) register num_p np; {
if(np->n_number<256) {
outbyte( (byte) sp_ilb1) ;
outbyte( (byte) (np->n_number) );
} else {
outbyte( (byte) sp_ilb2) ;
outshort((short) np->n_number);
}
}
outsym(sp) register sym_p sp; {
register byte *p;
register unsigned num;
if (sp->s_name[0] == '.') {
num = atoi(&sp->s_name[1]);
if (num < 256) {
outbyte( (byte) sp_dlb1) ;
outbyte( (byte) (num) );
} else {
outbyte( (byte) sp_dlb2) ;
outshort((short) num);
}
} else {
p= sp->s_name;
while (*p && p < &sp->s_name[IDL])
p++;
num = p - sp->s_name;
outbyte( (byte) (sp->s_flags&SYMPRO ? sp_pnam : sp_dnam) );
outint((short) num);
p = sp->s_name;
while (num--)
outbyte( (byte) *p++ );
}
}

View File

@@ -1,101 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "assert.h"
#include "param.h"
#include "types.h"
#include "line.h"
#include "proinf.h"
#include "alloc.h"
#include "../../h/em_spec.h"
#include "../../h/em_pseu.h"
#include "../../h/em_mes.h"
#include "ext.h"
/*
* (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
*
* Author: Hans van Staveren
*/
regvar(ap) register arg_p ap; {
register reg_p rp;
register i;
rp = newreg();
i=0;
while (ap!=(arg_p)0 && ap->a_typ==ARGOFF && i<4) {
rp->r_par[i++]=ap->a_a.a_offset;
ap=ap->a_next;
}
/*
* Omit incomplete messages
*/
switch(i) {
default:assert(FALSE);
case 0:
case 1:
case 2: oldreg(rp); return;
case 3: rp->r_par[3]= (offset) 0; break;
case 4: break;
}
rp->r_next = curpro.freg;
curpro.freg = rp;
}
inreg(off) offset off; {
register reg_p rp;
for (rp=curpro.freg; rp != (reg_p) 0; rp=rp->r_next)
if( rp->r_par[0] == off)
return(TRUE);
return(FALSE);
}
outregs() {
register reg_p rp,tp;
register i;
for(rp=curpro.freg; rp != (reg_p) 0; rp = tp) {
tp = rp->r_next;
if (rp->r_par[3] != 0) {
outinst(ps_mes);
outoff((offset)ms_reg);
for(i=0;i<4;i++)
outoff(rp->r_par[i]);
outinst(sp_cend);
}
oldreg(rp);
}
/* List of register messages is followed by an empty ms_reg
* unless an ms_gto was in this procedure, then the ms_gto
* will be output. Kludgy.
*/
outinst(ps_mes);
outoff((offset)(curpro.gtoproc? ms_gto : ms_reg));
outinst(sp_cend);
curpro.freg = (reg_p) 0;
}
incregusage(off) offset off; {
register reg_p rp;
for(rp=curpro.freg; rp != (reg_p) 0; rp=rp->r_next)
if (rp->r_par[0]==off) {
rp->r_par[3]++;
return;
}
}

View File

@@ -1,76 +0,0 @@
%{
#ifndef NORCSID
static char rcsid2[] = "$Header$";
#endif
/*
* (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
*
* Author: Hans van Staveren
*/
extern long atol();
%}
%%
notreg return(NOTREG);
sfit return(SFIT);
ufit return(UFIT);
rotate return(ROTATE);
p return(PSIZE);
w return(WSIZE);
defined return(DEFINED);
samesign return(SAMESIGN);
rom return(ROM);
[a-zA-Z]{3} {
int m;
m = mlookup(yytext);
if (m==0) {
REJECT;
} else {
yylval.y_int = m;
return(MNEM);
}
}
"&&" return(AND2);
"||" return(OR2);
"&" return(AND1);
"|" return(OR1);
"^" return(XOR1);
"+" return(ARPLUS);
"-" return(ARMINUS);
"*" return(ARTIMES);
"/" return(ARDIVIDE);
"%" return(ARMOD);
"==" return(CMPEQ);
"!=" return(CMPNE);
"<" return(CMPLT);
"<=" return(CMPLE);
">" return(CMPGT);
">=" return(CMPGE);
"!" return(NOT);
"~" return(COMP);
"<<" return(LSHIFT);
">>" return(RSHIFT);
[0-9]+ { long l= atol(yytext);
if (l>32767) yyerror("Number too big");
yylval.y_int= (int) l;
return(NUMBER);
}
[ \t] ;
. return(yytext[0]);
\n { lino++; return(yytext[0]); }
:[ \t]*\n[ \t]+ { lino++; return(':'); }
^"# "[0-9]+.*\n { lino=atoi(yytext+2); }
^\#.*\n { lino++; }

View File

@@ -1,33 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include "param.h"
#include "types.h"
/*
* (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
*
* Author: Hans van Staveren
*/
bool special(lpp,bp,patlen)
line_p *lpp;
byte *bp;
int patlen;
{
return(FALSE);
}

View File

@@ -1,9 +0,0 @@
: '$Header$'
while true
do
(echo ' mes 2,2,2
pro $foo,0';cat;echo ' end') >t.e
ack -Ropt=${1-opt} -O -c.m t.e;ack -c.e t.m
cat t.e
echo '===== next case (interrupt to stop) ====='
done

View File

@@ -1,21 +0,0 @@
/* $Header$ */
typedef char byte;
typedef char bool;
typedef struct line line_t;
typedef struct line *line_p;
typedef struct sym sym_t;
typedef struct sym *sym_p;
typedef struct num num_t;
typedef struct num *num_p;
typedef struct arg arg_t;
typedef struct arg *arg_p;
typedef struct argbytes argb_t;
typedef struct argbytes *argb_p;
typedef struct regs reg_t;
typedef struct regs *reg_p;
#ifdef LONGOFF
typedef long offset;
#else
typedef short offset;
#endif

View File

@@ -1,62 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "assert.h"
#include "lookup.h"
#include "proinf.h"
#include "optim.h"
#include "ext.h"
/*
* (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
*
* Author: Hans van Staveren
*/
/* VARARGS1 */
error(s,a) char *s,*a; {
fprintf(stderr,"%s: error on line %u",progname,linecount);
if (prodepth != 0)
fprintf(stderr,"(%.*s)",IDL,curpro.symbol->s_name);
fprintf(stderr,": ");
fprintf(stderr,s,a);
fprintf(stderr,"\n");
abort();
exit(-1);
}
#ifndef NDEBUG
badassertion(file,line) char *file; unsigned line; {
fprintf(stderr,"assertion failed file %s, line %u\n",file,line);
error("assertion");
}
#endif
#ifdef DIAGOPT
optim(n) {
fprintf(stderr,"Made optimization %d",n);
if (inpro)
fprintf(stderr," (%.*s)",IDL,curpro.symbol->s_name);
fprintf(stderr,"\n");
}
#endif

View File

@@ -1,40 +0,0 @@
#ifndef NORCSID
static char rcsid[] = "$Header$";
#endif
#include <stdio.h>
#include "param.h"
#include "types.h"
#include "lookup.h"
#include "proinf.h"
/*
* (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
*
* Author: Hans van Staveren
*/
unsigned linecount = 0; /* "line"number for errormessages */
int prodepth = 0; /* Level of nesting */
bool Lflag = 0; /* make library module */
bool nflag = 0; /* do not optimize */
line_p instrs,pseudos; /* pointers to chains */
sym_p symhash[NSYMHASH]; /* array of pointers to chains */
FILE *outfile;
char template[] = "/usr/tmp/emoptXXXXXX";
offset wordsize = 0;
offset pointersize = 0;
char *progname;
proinf curpro; /* collected information about current pro */