Added C_insertpart mechanism
This commit is contained in:
parent
19897803d4
commit
83bc77ad51
|
@ -6,3 +6,8 @@ k
|
||||||
make.em.gen
|
make.em.gen
|
||||||
make.fun
|
make.fun
|
||||||
failed.c
|
failed.c
|
||||||
|
getid.c
|
||||||
|
insert.c
|
||||||
|
internerr.c
|
||||||
|
io.c
|
||||||
|
insert.h
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
EMHOME = ../../..
|
EMHOME = ../../..
|
||||||
INSTALL = $(EMHOME)/modules/install
|
INSTALL = $(EMHOME)/modules/install
|
||||||
COMPARE = $(EMHOME)/modules/compare
|
COMPARE = $(EMHOME)/modules/compare
|
||||||
|
INCORE = -DINCORE
|
||||||
|
CFLAGS = -I$(EMHOME)/h -I$(EMHOME)/modules/h -O
|
||||||
|
OBS = failed.o insert.o internerr.o io.o getid.o
|
||||||
|
|
||||||
all: libeme.a libemk.a em_code.3
|
all: libeme.a libemk.a em_code.3
|
||||||
rm -f C_*.c
|
rm -f C_*.c
|
||||||
|
@ -19,15 +22,15 @@ em_code.3: em_code.3X
|
||||||
-sh -c 'tbl < em_code.3X > em_code.3'
|
-sh -c 'tbl < em_code.3X > em_code.3'
|
||||||
-sh -c 'if test -s em_code.3 ; then : ; else cp em_code.3X em_code.3 ; fi '
|
-sh -c 'if test -s em_code.3 ; then : ; else cp em_code.3X em_code.3 ; fi '
|
||||||
|
|
||||||
libeme.a: make.sh e/em_private.h e/em.c failed.c
|
libeme.a: make.sh e/em_private.h e/em.c $(OBS)
|
||||||
EMHOME=$(EMHOME); export EMHOME; sh make.sh e
|
EMHOME=$(EMHOME); export EMHOME; sh make.sh e
|
||||||
-sh -c 'ranlib libeme.a'
|
-sh -c 'ranlib libeme.a'
|
||||||
|
|
||||||
libemk.a: make.sh k/em_private.h k/em.c failed.c
|
libemk.a: make.sh k/em_private.h k/em.c $(OBS)
|
||||||
EMHOME=$(EMHOME); export EMHOME; sh make.sh k
|
EMHOME=$(EMHOME); export EMHOME; sh make.sh k
|
||||||
-sh -c 'ranlib libemk.a'
|
-sh -c 'ranlib libemk.a'
|
||||||
|
|
||||||
make.sh: em.gen em.nogen
|
make.sh: em.gen em.nogen make.fun
|
||||||
make.fun em.gen em.nogen | sh
|
make.fun em.gen em.nogen | sh
|
||||||
|
|
||||||
em.gen: make.em.gen $(EMHOME)/etc/em_table
|
em.gen: make.em.gen $(EMHOME)/etc/em_table
|
||||||
|
@ -50,3 +53,9 @@ lintlib: make.sh
|
||||||
lint -I../../h -I../../../h -Ie -Ceme *.c e/*.c
|
lint -I../../h -I../../../h -Ie -Ceme *.c e/*.c
|
||||||
lint -I../../h -I../../../h -Ik -Cemk *.c k/*.c
|
lint -I../../h -I../../../h -Ik -Cemk *.c k/*.c
|
||||||
mv llib-leme.ln llib-lemk.ln $(EMHOME)/modules/lib
|
mv llib-leme.ln llib-lemk.ln $(EMHOME)/modules/lib
|
||||||
|
|
||||||
|
insert.o: insert.c insert.h
|
||||||
|
$(CC) $(CFLAGS) -c $(INCORE) insert.c
|
||||||
|
|
||||||
|
io.o: io.c insert.h
|
||||||
|
$(CC) $(CFLAGS) -c $(INCORE) io.c
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
#include "em_private.h"
|
#include "em_private.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
putbyte(), C_open() and C_close() are the basic routines for
|
|
||||||
respectively write on, open and close the outpt file.
|
|
||||||
The C_pt_*() functions serve as formatting functions of the
|
The C_pt_*() functions serve as formatting functions of the
|
||||||
various EM language constructs.
|
various EM language constructs.
|
||||||
See "Description of a Machine Architecture for use with
|
See "Description of a Machine Architecture for use with
|
||||||
|
@ -18,65 +16,12 @@
|
||||||
names.
|
names.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static File *ofp = 0;
|
|
||||||
static char obuf[BUFSIZ];
|
|
||||||
static char *opp = obuf;
|
|
||||||
|
|
||||||
static
|
|
||||||
flush() {
|
|
||||||
if (sys_write(ofp, &obuf[0], opp - &obuf[0]) == 0) {
|
|
||||||
C_failed();
|
|
||||||
}
|
|
||||||
opp = &obuf[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
#define Xputbyte(c) if (opp == &obuf[BUFSIZ]) flush(); *opp++ = (c)
|
|
||||||
|
|
||||||
static
|
|
||||||
C_putbyte(b)
|
|
||||||
int b;
|
|
||||||
{
|
|
||||||
Xputbyte(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
C_init(w, p)
|
|
||||||
arith w, p;
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
C_open(nm) /* open file for readable code outpt */
|
|
||||||
char *nm;
|
|
||||||
{
|
|
||||||
if (nm == 0)
|
|
||||||
ofp = STDOUT; /* standard outpt */
|
|
||||||
else
|
|
||||||
if (sys_open(nm, OP_WRITE, &ofp) == 0)
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
C_close()
|
|
||||||
{
|
|
||||||
if (opp != obuf) flush();
|
|
||||||
if (ofp != STDOUT)
|
|
||||||
sys_close(ofp);
|
|
||||||
ofp = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
C_busy()
|
|
||||||
{
|
|
||||||
return ofp != 0; /* true if code is being generated */
|
|
||||||
}
|
|
||||||
|
|
||||||
C_magic()
|
C_magic()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*** the readable code generating routines ***/
|
/*** the readable code generating routines ***/
|
||||||
|
|
||||||
static char buf[512];
|
|
||||||
|
|
||||||
static
|
static
|
||||||
wrs(s)
|
wrs(s)
|
||||||
register char *s;
|
register char *s;
|
||||||
|
@ -93,6 +38,8 @@ C_pt_dnam(s)
|
||||||
C_pt_ilb(l)
|
C_pt_ilb(l)
|
||||||
label l;
|
label l;
|
||||||
{
|
{
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
sprint(buf, "*%ld", (long) l);
|
sprint(buf, "*%ld", (long) l);
|
||||||
wrs(buf);
|
wrs(buf);
|
||||||
}
|
}
|
||||||
|
@ -110,6 +57,8 @@ C_pt_op(x)
|
||||||
C_pt_cst(l)
|
C_pt_cst(l)
|
||||||
arith l;
|
arith l;
|
||||||
{
|
{
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
sprint(buf, "%ld", (long) l);
|
sprint(buf, "%ld", (long) l);
|
||||||
wrs(buf);
|
wrs(buf);
|
||||||
}
|
}
|
||||||
|
@ -118,13 +67,12 @@ C_pt_scon(x, y)
|
||||||
char *x;
|
char *x;
|
||||||
arith y;
|
arith y;
|
||||||
{
|
{
|
||||||
char buf[1024];
|
char xbuf[1024];
|
||||||
char sbuf[1024];
|
register char *p;
|
||||||
register char *p, *q = &sbuf[0];
|
|
||||||
char *bts2str();
|
char *bts2str();
|
||||||
|
|
||||||
C_putbyte('\'');
|
C_putbyte('\'');
|
||||||
p = bts2str(x, (int) y, buf);
|
p = bts2str(x, (int) y, xbuf);
|
||||||
while (*p) {
|
while (*p) {
|
||||||
if (*p == '\'')
|
if (*p == '\'')
|
||||||
C_putbyte('\\');
|
C_putbyte('\\');
|
||||||
|
@ -143,6 +91,8 @@ C_pt_ps(x)
|
||||||
C_pt_dlb(l)
|
C_pt_dlb(l)
|
||||||
label l;
|
label l;
|
||||||
{
|
{
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
sprint(buf, ".%ld", (long) l);
|
sprint(buf, ".%ld", (long) l);
|
||||||
wrs(buf);
|
wrs(buf);
|
||||||
}
|
}
|
||||||
|
@ -151,6 +101,8 @@ C_pt_doff(l, v)
|
||||||
label l;
|
label l;
|
||||||
arith v;
|
arith v;
|
||||||
{
|
{
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
C_pt_dlb(l);
|
C_pt_dlb(l);
|
||||||
if (v != 0) {
|
if (v != 0) {
|
||||||
sprint(buf,"+%ld", (long) v);
|
sprint(buf,"+%ld", (long) v);
|
||||||
|
@ -162,6 +114,8 @@ C_pt_noff(s, v)
|
||||||
char *s;
|
char *s;
|
||||||
arith v;
|
arith v;
|
||||||
{
|
{
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
wrs(s);
|
wrs(s);
|
||||||
if (v != 0) {
|
if (v != 0) {
|
||||||
sprint(buf,"+%ld", (long) v);
|
sprint(buf,"+%ld", (long) v);
|
||||||
|
@ -179,6 +133,8 @@ C_pt_pnam(s)
|
||||||
C_pt_dfilb(l)
|
C_pt_dfilb(l)
|
||||||
label l;
|
label l;
|
||||||
{
|
{
|
||||||
|
char buf[16];
|
||||||
|
|
||||||
sprint(buf, "%ld", (long) l);
|
sprint(buf, "%ld", (long) l);
|
||||||
wrs(buf);
|
wrs(buf);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
.TH EM_CODE 3ACK "86/04/02"
|
.TH EM_CODE 3ACK "$Revision$"
|
||||||
.ad
|
.ad
|
||||||
.SH NAME
|
.SH NAME
|
||||||
emcode \- EM code interface for compilers
|
emcode \- EM code interface for compilers
|
||||||
|
@ -53,6 +53,17 @@ emcode \- EM code interface for compilers
|
||||||
.BI C_ mnem _dlb()
|
.BI C_ mnem _dlb()
|
||||||
.BI C_ mnem _dnam()
|
.BI C_ mnem _dnam()
|
||||||
.BI C_ mnem _narg()
|
.BI C_ mnem _narg()
|
||||||
|
.PP
|
||||||
|
.B C_insertpart(id)
|
||||||
|
.B int id;
|
||||||
|
.PP
|
||||||
|
.B C_beginpart(id)
|
||||||
|
.B int id;
|
||||||
|
.PP
|
||||||
|
.B C_endpart(id)
|
||||||
|
.B int id;
|
||||||
|
.PP
|
||||||
|
.B int C_getid()
|
||||||
.fi
|
.fi
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
This package provides a procedural EM code interface to be used in
|
This package provides a procedural EM code interface to be used in
|
||||||
|
@ -386,6 +397,33 @@ is a numeric label.
|
||||||
The latter two routines have the (possibly zero) offset
|
The latter two routines have the (possibly zero) offset
|
||||||
.I o
|
.I o
|
||||||
as second parameter.
|
as second parameter.
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.IR C_insertpart ,
|
||||||
|
.IR C_beginpart ,
|
||||||
|
and
|
||||||
|
.I C_endpart
|
||||||
|
routines together implement a mechanism for re-arranging the generated code.
|
||||||
|
A call to
|
||||||
|
.I C_insertpart
|
||||||
|
indicates that part
|
||||||
|
.I id
|
||||||
|
is to be inserted at the current position.
|
||||||
|
The routines
|
||||||
|
.I C_beginpart
|
||||||
|
and
|
||||||
|
.I C_endpart
|
||||||
|
indicate begin and end of part
|
||||||
|
.IR id .
|
||||||
|
The order in which the parts are defined is not significant.
|
||||||
|
However, when
|
||||||
|
.I C_close
|
||||||
|
is called, all parts that have been inserted, must also be defined.
|
||||||
|
.PP
|
||||||
|
The routine
|
||||||
|
.I C_getid
|
||||||
|
can be used to obtain a valid and unique part
|
||||||
|
.IR id .
|
||||||
.SH FILES
|
.SH FILES
|
||||||
.nf
|
.nf
|
||||||
~em/modules/h/em.h
|
~em/modules/h/em.h
|
||||||
|
@ -394,11 +432,11 @@ as second parameter.
|
||||||
.fi
|
.fi
|
||||||
.SH MODULES
|
.SH MODULES
|
||||||
.nf
|
.nf
|
||||||
libemk.a: system(3L), string(3L)
|
libemk.a: alloc(3), system(3), string(3)
|
||||||
libeme.a: print(3L), system(3L), string(3L)
|
libeme.a: alloc(3), print(3), system(3), string(3)
|
||||||
.fi
|
.fi
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
read_em(3L), em_mes(3L)
|
read_em(3), em_mes(3)
|
||||||
.SH REFERENCES
|
.SH REFERENCES
|
||||||
.IP [EM] 6
|
.IP [EM] 6
|
||||||
Andrew S. Tanenbaum, Hans van Staveren, Ed G. Keizer, Johan W. Stevenson,
|
Andrew S. Tanenbaum, Hans van Staveren, Ed G. Keizer, Johan W. Stevenson,
|
||||||
|
@ -410,14 +448,18 @@ Informatica Rapport IR-81, Vrije Universiteit, Amsterdam, 1983.
|
||||||
.I C_open
|
.I C_open
|
||||||
returns 1 if the open is successful and 0 if not.
|
returns 1 if the open is successful and 0 if not.
|
||||||
.PP
|
.PP
|
||||||
When a write fails, the routine
|
When a read, write or open fails, the routine
|
||||||
.I C_failed
|
.I C_failed
|
||||||
is called. The user can override its default definition by supplying his
|
is called. The user can override its default definition by supplying his
|
||||||
own. The default just gives an error message and quits.
|
own. The default just gives an error message and quits.
|
||||||
|
.PP
|
||||||
|
When an error occurs with the
|
||||||
|
.I C_insertpart
|
||||||
|
mechanism, the routine
|
||||||
|
.I C_internal_error
|
||||||
|
is called. Again, the user can override its default definition by supplying his
|
||||||
|
own. Such errors, however, are caused by a programming error of the user.
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
It is not possible to indicate that the argument of
|
It is not possible to indicate that the argument of
|
||||||
.B C_con_cst ()
|
.B C_con_cst ()
|
||||||
must be seen as an unsigned value.
|
must be seen as an unsigned value.
|
||||||
.PP
|
|
||||||
.I C_failed
|
|
||||||
is never called when generating readable EM code.
|
|
||||||
|
|
|
@ -7,6 +7,6 @@
|
||||||
|
|
||||||
C_failed()
|
C_failed()
|
||||||
{
|
{
|
||||||
sys_write(STDERR,"write failed\n",13);
|
sys_write(STDERR,"read, write, or open failed\n",28);
|
||||||
sys_stop(S_EXIT);
|
sys_stop(S_EXIT);
|
||||||
}
|
}
|
||||||
|
|
11
modules/src/em_code/getid.c
Normal file
11
modules/src/em_code/getid.c
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/* $Header$ */
|
||||||
|
|
||||||
|
/* Get a unique id for C_insertpart, etc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
C_getid()
|
||||||
|
{
|
||||||
|
static int id = 0;
|
||||||
|
|
||||||
|
return ++id;
|
||||||
|
}
|
186
modules/src/em_code/insert.c
Normal file
186
modules/src/em_code/insert.c
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
/* $Header$ */
|
||||||
|
|
||||||
|
/* Implementation of C_insertpart, C_beginpart, and C_endpart.
|
||||||
|
Basic methodology: place the parts either in memory or on a temporary
|
||||||
|
file, in the order received, and remember this order. Then, in a second
|
||||||
|
"pass", write out the code.
|
||||||
|
An optimization is possible: as long as the order in which the parts
|
||||||
|
are received corresponds to the order in which they must be written,
|
||||||
|
they can be written immediately.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <alloc.h>
|
||||||
|
#include "insert.h"
|
||||||
|
|
||||||
|
#ifdef INCORE
|
||||||
|
#define C_switchtotmp() (C_ontmpfile = 1)
|
||||||
|
#define C_switchtoout() (C_ontmpfile = 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int
|
||||||
|
available(part)
|
||||||
|
int part;
|
||||||
|
{
|
||||||
|
/* See if part "part", and all the parts it consists of,
|
||||||
|
are available. Return 1 if they are, 0 otherwize
|
||||||
|
*/
|
||||||
|
register Part *p = C_findpart(part);
|
||||||
|
register PartOfPart *pp;
|
||||||
|
int retval = 1;
|
||||||
|
|
||||||
|
if (p == 0) return 0;
|
||||||
|
|
||||||
|
if (p->p_flags & BUSY) {
|
||||||
|
/* recursive call ends up here, and this just should
|
||||||
|
not happen. It is an error of the programmer using
|
||||||
|
this module.
|
||||||
|
*/
|
||||||
|
C_internal_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
p->p_flags |= BUSY;
|
||||||
|
|
||||||
|
pp = p->p_parts;
|
||||||
|
while (pp) {
|
||||||
|
if (pp->pp_type == INSERT && ! available(pp->pp_id)) {
|
||||||
|
retval = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else pp = pp->pp_next;
|
||||||
|
}
|
||||||
|
p->p_flags &= ~BUSY;
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Part *
|
||||||
|
mkpart(part)
|
||||||
|
int part;
|
||||||
|
{
|
||||||
|
/* Create a Part structure with id "part", and return a
|
||||||
|
pointer to it, after checking that is does not exist
|
||||||
|
already.
|
||||||
|
*/
|
||||||
|
register Part *p = C_findpart(part);
|
||||||
|
register int index = part % TABSIZ;
|
||||||
|
|
||||||
|
if (p != 0) {
|
||||||
|
/* multiple defined part ... */
|
||||||
|
C_internal_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
p = (Part *) Malloc(sizeof(Part));
|
||||||
|
p->p_id = part;
|
||||||
|
p->p_next = C_stable[index];
|
||||||
|
C_stable[index] = p;
|
||||||
|
p->p_parts = 0;
|
||||||
|
p->p_flags = 0;
|
||||||
|
p->p_prevpart = 0;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
end_partofpart(p)
|
||||||
|
register Part *p;
|
||||||
|
{
|
||||||
|
/* End the current chunk of part *p.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
register PartOfPart *pp = p->p_parts;
|
||||||
|
|
||||||
|
pp->pp_end = C_current_out;
|
||||||
|
if (pp->pp_begin == pp->pp_end) {
|
||||||
|
/* nothing in this chunk, so give it back */
|
||||||
|
p->p_parts = pp->pp_next;
|
||||||
|
free((char *) pp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
resume(p)
|
||||||
|
register Part *p;
|
||||||
|
{
|
||||||
|
/* Resume part "p", by creating a new PartOfPart structure
|
||||||
|
for it.
|
||||||
|
*/
|
||||||
|
register PartOfPart *pp = (PartOfPart *) Malloc(sizeof(PartOfPart));
|
||||||
|
|
||||||
|
C_switchtotmp();
|
||||||
|
C_curr_part = p;
|
||||||
|
pp->pp_next = p->p_parts;
|
||||||
|
p->p_parts = pp;
|
||||||
|
pp->pp_type = TEXT;
|
||||||
|
pp->pp_begin = C_current_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
C_insertpart(part)
|
||||||
|
int part;
|
||||||
|
{
|
||||||
|
/* Insert part "part" in the current part. If C_sequential is
|
||||||
|
still set and the part to be inserted is available now,
|
||||||
|
just write it out.
|
||||||
|
*/
|
||||||
|
register Part *p;
|
||||||
|
register PartOfPart *pp;
|
||||||
|
|
||||||
|
if (C_sequential && available(part)) {
|
||||||
|
outpart(part);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (C_sequential) {
|
||||||
|
/* stop the sequential stuff, by creating a part */
|
||||||
|
C_sequential = 0;
|
||||||
|
p = mkpart(0);
|
||||||
|
C_curr_part = p;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
p = C_curr_part;
|
||||||
|
end_partofpart(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now, add the insertion of "part" to the current part. */
|
||||||
|
pp = (PartOfPart *) Malloc(sizeof(PartOfPart));
|
||||||
|
pp->pp_next = p->p_parts;
|
||||||
|
p->p_parts = pp;
|
||||||
|
pp->pp_type = INSERT;
|
||||||
|
pp->pp_id = part;
|
||||||
|
resume(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
C_beginpart(part)
|
||||||
|
int part;
|
||||||
|
{
|
||||||
|
/* Now follows the definition for part "part".
|
||||||
|
Suspend the current part, and add part "part" to the
|
||||||
|
table.
|
||||||
|
*/
|
||||||
|
register Part *p = mkpart(part);
|
||||||
|
|
||||||
|
end_partofpart(C_curr_part);
|
||||||
|
|
||||||
|
p->p_prevpart = C_curr_part;
|
||||||
|
resume(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
C_endpart(part)
|
||||||
|
int part;
|
||||||
|
{
|
||||||
|
/* End the current part. The parameter "part" is just there
|
||||||
|
for the checking. Do we really need it ???
|
||||||
|
*/
|
||||||
|
register Part *p = C_curr_part;
|
||||||
|
|
||||||
|
if (p->p_id != part) {
|
||||||
|
/* illegal C_endpart ... */
|
||||||
|
C_internal_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
end_partofpart(p);
|
||||||
|
if (p->p_prevpart) resume(p->p_prevpart);
|
||||||
|
else {
|
||||||
|
C_curr_part = 0;
|
||||||
|
C_switchtoout();
|
||||||
|
}
|
||||||
|
}
|
43
modules/src/em_code/insert.h
Normal file
43
modules/src/em_code/insert.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/* Structures used for the C_insertpart, C_beginpart, and C_endpart
|
||||||
|
mechanism. Each part consists of a list of chunks. Each chunk is
|
||||||
|
either another part, or a piece of text limited by a begin- and an
|
||||||
|
end-pointer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct partofpart {
|
||||||
|
struct partofpart *pp_next;
|
||||||
|
char pp_type;
|
||||||
|
#define TEXT 0
|
||||||
|
#define INSERT 1
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
long ppu_begin, ppu_end;
|
||||||
|
} ppu_s;
|
||||||
|
int ppu_id;
|
||||||
|
} pp_u;
|
||||||
|
#define pp_begin pp_u.ppu_s.ppu_begin
|
||||||
|
#define pp_end pp_u.ppu_s.ppu_end
|
||||||
|
#define pp_id pp_u.ppu_id
|
||||||
|
} PartOfPart;
|
||||||
|
|
||||||
|
typedef struct part {
|
||||||
|
struct part *p_next; /* next part in hash chain */
|
||||||
|
char p_flags;
|
||||||
|
#define BUSY 1
|
||||||
|
PartOfPart *p_parts; /* chunks of this part */
|
||||||
|
struct part *p_prevpart; /* implements stack of active parts */
|
||||||
|
int p_id; /* id of this part */
|
||||||
|
} Part;
|
||||||
|
|
||||||
|
#define outpart(xxx) C_out_parts(C_findpart(xxx)->p_parts)
|
||||||
|
|
||||||
|
#define TABSIZ 32
|
||||||
|
|
||||||
|
extern int
|
||||||
|
C_ontmpfile, C_sequential;
|
||||||
|
extern Part
|
||||||
|
*C_curr_part, *C_stable[];
|
||||||
|
extern long
|
||||||
|
C_current_out;
|
||||||
|
extern Part
|
||||||
|
*C_findpart();
|
12
modules/src/em_code/internerr.c
Normal file
12
modules/src/em_code/internerr.c
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/* $Header$ */
|
||||||
|
/*
|
||||||
|
* (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
|
||||||
|
* See the copyright notice in the ACK home directory, in the file "Copyright".
|
||||||
|
*/
|
||||||
|
#include <system.h>
|
||||||
|
|
||||||
|
C_internal_error()
|
||||||
|
{
|
||||||
|
sys_write(STDERR,"internal error\n",15);
|
||||||
|
sys_stop(S_EXIT);
|
||||||
|
}
|
247
modules/src/em_code/io.c
Normal file
247
modules/src/em_code/io.c
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
/* $Header$ */
|
||||||
|
|
||||||
|
/* I/O part of em_code module.
|
||||||
|
Also contains C_open, C_close
|
||||||
|
*/
|
||||||
|
#include <system.h>
|
||||||
|
#include <alloc.h>
|
||||||
|
#include <em_path.h>
|
||||||
|
#include <em_arith.h>
|
||||||
|
#include "insert.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
C_ontmpfile = 0,
|
||||||
|
C_sequential = 1;
|
||||||
|
Part
|
||||||
|
*C_curr_part, *C_stable[TABSIZ];
|
||||||
|
long
|
||||||
|
C_current_out;
|
||||||
|
|
||||||
|
static char *BASE;
|
||||||
|
static File *ofp;
|
||||||
|
|
||||||
|
#ifndef INCORE
|
||||||
|
static File *tfr, *old_ofp;
|
||||||
|
static char *tmpfile;
|
||||||
|
char *strcpy(), *strcat(), *mktemp();
|
||||||
|
static char *ibuf = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static char obuf[BUFSIZ];
|
||||||
|
static char *opp = obuf;
|
||||||
|
|
||||||
|
static
|
||||||
|
flush() {
|
||||||
|
if (opp != obuf && sys_write(ofp, obuf, opp - obuf) == 0) {
|
||||||
|
C_failed();
|
||||||
|
}
|
||||||
|
opp = obuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define put(c) if (opp == &obuf[BUFSIZ]) flush(); *opp++ = (c)
|
||||||
|
|
||||||
|
C_putbyte(c)
|
||||||
|
int c;
|
||||||
|
{
|
||||||
|
if (C_ontmpfile) {
|
||||||
|
#ifdef INCORE
|
||||||
|
static unsigned sz;
|
||||||
|
|
||||||
|
if (BASE == 0) {
|
||||||
|
BASE = Malloc(BUFSIZ);
|
||||||
|
sz = BUFSIZ;
|
||||||
|
}
|
||||||
|
else if (C_current_out >= sz) {
|
||||||
|
BASE = Srealloc(BASE, (sz <<= 1));
|
||||||
|
}
|
||||||
|
*(BASE + C_current_out) = c;
|
||||||
|
#endif
|
||||||
|
C_current_out++;
|
||||||
|
#ifdef INCORE
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
put(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef INCORE
|
||||||
|
C_switchtotmp()
|
||||||
|
{
|
||||||
|
if (tmpfile == 0) {
|
||||||
|
static char tmpbuf[64];
|
||||||
|
register char *p = tmpbuf;
|
||||||
|
|
||||||
|
strcpy(p, TMP_DIR);
|
||||||
|
strcat(p, "/CodeXXXXXX");
|
||||||
|
tmpfile = mktemp(p);
|
||||||
|
if (! sys_open(p, OP_WRITE, &old_ofp)) {
|
||||||
|
C_failed();
|
||||||
|
}
|
||||||
|
if (! sys_open(p, OP_READ, &tfr)) {
|
||||||
|
C_failed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! C_ontmpfile) {
|
||||||
|
File *p = ofp;
|
||||||
|
|
||||||
|
flush();
|
||||||
|
ofp = old_ofp;
|
||||||
|
old_ofp = p;
|
||||||
|
C_ontmpfile = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
C_switchtoout()
|
||||||
|
{
|
||||||
|
if (C_ontmpfile) {
|
||||||
|
File *p = ofp;
|
||||||
|
|
||||||
|
flush();
|
||||||
|
ofp = old_ofp;
|
||||||
|
old_ofp = p;
|
||||||
|
C_ontmpfile = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
C_init(w, p)
|
||||||
|
arith w, p;
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
C_open(nm)
|
||||||
|
char *nm;
|
||||||
|
{
|
||||||
|
/* Open file "nm" for output
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (nm == 0)
|
||||||
|
ofp = STDOUT; /* standard output */
|
||||||
|
else
|
||||||
|
if (sys_open(nm, OP_WRITE, &ofp) == 0)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
C_close()
|
||||||
|
{
|
||||||
|
/* Finish the code-generation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCORE
|
||||||
|
flush();
|
||||||
|
if (tmpfile) {
|
||||||
|
C_switchtotmp();
|
||||||
|
sys_close(ofp);
|
||||||
|
ofp = old_ofp;
|
||||||
|
#else
|
||||||
|
if (BASE) {
|
||||||
|
#endif
|
||||||
|
if (C_curr_part) {
|
||||||
|
C_curr_part->p_parts->pp_end = C_current_out;
|
||||||
|
}
|
||||||
|
if (! C_sequential) {
|
||||||
|
outpart(0);
|
||||||
|
}
|
||||||
|
#ifndef INCORE
|
||||||
|
sys_close(tfr);
|
||||||
|
sys_remove(tmpfile);
|
||||||
|
if (ibuf) free(ibuf);
|
||||||
|
#else
|
||||||
|
free(BASE);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
flush();
|
||||||
|
if (ofp != STDOUT)
|
||||||
|
sys_close(ofp);
|
||||||
|
ofp = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
C_busy()
|
||||||
|
{
|
||||||
|
return ofp != 0; /* true if code is being generated */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef INCORE
|
||||||
|
static int
|
||||||
|
getbyte(b)
|
||||||
|
long b;
|
||||||
|
{
|
||||||
|
/* Get the byte at offset "b" from the start of the
|
||||||
|
temporary file, and try to do so in an efficient way.
|
||||||
|
*/
|
||||||
|
static long start_core, curr_pos;
|
||||||
|
|
||||||
|
if (b < start_core || b >= curr_pos) {
|
||||||
|
/* the block wanted is not in core, so get it */
|
||||||
|
long nb = (b & ~(BUFSIZ - 1));
|
||||||
|
int n;
|
||||||
|
|
||||||
|
flush();
|
||||||
|
if (nb != curr_pos) {
|
||||||
|
if (sys_seek(tfr, nb, 0, &curr_pos) == 0) {
|
||||||
|
C_failed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (! ibuf) {
|
||||||
|
ibuf = Malloc(BUFSIZ);
|
||||||
|
}
|
||||||
|
if (sys_read(tfr, ibuf, BUFSIZ, &n) == 0) {
|
||||||
|
C_failed();
|
||||||
|
}
|
||||||
|
curr_pos += n;
|
||||||
|
start_core = nb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ibuf[(int) (b - start_core)];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
C_out_parts(pp)
|
||||||
|
register PartOfPart *pp;
|
||||||
|
{
|
||||||
|
/* Output the list of chunks started by "pp".
|
||||||
|
The list is build in reverse order, so this routine is
|
||||||
|
recursive.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!pp) return;
|
||||||
|
if (pp->pp_next) C_out_parts(pp->pp_next);
|
||||||
|
|
||||||
|
if (pp->pp_type == INSERT) {
|
||||||
|
outpart(pp->pp_id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* copy the chunk to output */
|
||||||
|
#ifdef INCORE
|
||||||
|
register char *s = BASE + pp->pp_begin;
|
||||||
|
char *se = BASE + pp->pp_end;
|
||||||
|
|
||||||
|
while (s < se) {
|
||||||
|
put(*s++);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
register long b = pp->pp_begin;
|
||||||
|
|
||||||
|
while (b < pp->pp_end) {
|
||||||
|
put(getbyte(b++));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Part *
|
||||||
|
C_findpart(part)
|
||||||
|
int part;
|
||||||
|
{
|
||||||
|
/* Look for part "part" in the table.
|
||||||
|
Return 0 if not present,
|
||||||
|
*/
|
||||||
|
register Part *p = C_stable[part % TABSIZ];
|
||||||
|
|
||||||
|
while (p && p->p_id != part) {
|
||||||
|
p = p->p_next;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
|
@ -13,8 +13,6 @@
|
||||||
#define put32(x) put16((int) x); put16((int) (x >> 16))
|
#define put32(x) put16((int) x); put16((int) (x >> 16))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
C_putbyte(), C_open() and C_close() are the basic routines for
|
|
||||||
respectively write on, open and close the output file.
|
|
||||||
The C_pt_*() functions serve as formatting functions of the
|
The C_pt_*() functions serve as formatting functions of the
|
||||||
various EM language constructs.
|
various EM language constructs.
|
||||||
See "Description of a Machine Architecture for use with
|
See "Description of a Machine Architecture for use with
|
||||||
|
@ -22,59 +20,6 @@
|
||||||
names.
|
names.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* supply a kind of buffered output */
|
|
||||||
|
|
||||||
static char obuf[BUFSIZ];
|
|
||||||
static char *opp = &obuf[0];
|
|
||||||
static File *ofp = 0;
|
|
||||||
|
|
||||||
static
|
|
||||||
flush() {
|
|
||||||
if (sys_write(ofp, &obuf[0], opp - &obuf[0]) == 0) {
|
|
||||||
C_failed();
|
|
||||||
}
|
|
||||||
opp = &obuf[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
#define Xputbyte(c) if (opp == &obuf[BUFSIZ]) flush(); *opp++ = (c)
|
|
||||||
|
|
||||||
C_putbyte(b)
|
|
||||||
int b;
|
|
||||||
{
|
|
||||||
Xputbyte(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define C_putbyte(c) Xputbyte(c)
|
|
||||||
|
|
||||||
C_init(w, p)
|
|
||||||
arith w, p;
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
C_open(nm) /* open file for compact code output */
|
|
||||||
char *nm;
|
|
||||||
{
|
|
||||||
if (nm == 0)
|
|
||||||
ofp = STDOUT; /* standard output */
|
|
||||||
else
|
|
||||||
if (sys_open(nm, OP_WRITE, &ofp) == 0)
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
C_close()
|
|
||||||
{
|
|
||||||
if (opp != &obuf[0]) flush();
|
|
||||||
if (ofp != STDOUT)
|
|
||||||
sys_close(ofp);
|
|
||||||
ofp = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
C_busy()
|
|
||||||
{
|
|
||||||
return ofp != 0; /* true if code is being generated */
|
|
||||||
}
|
|
||||||
|
|
||||||
C_magic()
|
C_magic()
|
||||||
{
|
{
|
||||||
put16(sp_magic);
|
put16(sp_magic);
|
||||||
|
|
|
@ -37,16 +37,14 @@ g:^NAME:s:^NAME \(.*\)$:cc -c -O -I$1 -I$EMHOME/modules/h -I$EMHOME/h \1.c:
|
||||||
1i
|
1i
|
||||||
cat >make.sh <<'--EOF--'
|
cat >make.sh <<'--EOF--'
|
||||||
: script for making lib
|
: script for making lib
|
||||||
rm -f *.o
|
rm -f C_*.o
|
||||||
.
|
.
|
||||||
$a
|
$a
|
||||||
rm -f libem$1.a
|
rm -f libem$1.a
|
||||||
ar rc libem$1.a *.o
|
cc -c -O -I$1 -I$EMHOME/modules/h -I$EMHOME/h $1/em.c
|
||||||
cc -c -O -I$1 -I. -I$EMHOME/modules/h -I$EMHOME/h $1/em.c
|
|
||||||
cc -c -O -I$EMHOME/modules/h -I$EMHOME/h failed.c
|
|
||||||
mv em.o em$1.o
|
mv em.o em$1.o
|
||||||
ar r libem$1.a em$1.o failed.o
|
ar rc libem$1.a C_*.o em$1.o insert.o io.o failed.o internerr.o getid.o
|
||||||
rm -f *.o
|
rm -f C_*.o
|
||||||
--EOF--
|
--EOF--
|
||||||
.
|
.
|
||||||
1,$p
|
1,$p
|
||||||
|
|
Loading…
Reference in a new issue