From 3b4b7cac60740ae41d92cdf05b5f1e13ae25dbd7 Mon Sep 17 00:00:00 2001 From: keie Date: Thu, 21 Jun 1984 10:57:59 +0000 Subject: [PATCH] Initial revision --- lib/6500/descr | 27 ++ lib/6809/descr | 31 ++ lib/descr/cpm | 25 ++ lib/descr/fe.src | 60 ++++ lib/descr/nascom | 28 ++ lib/em22/descr | 27 ++ lib/i80/descr | 27 ++ lib/i86/descr | 32 ++ lib/m68k2/descr | 30 ++ lib/m68k4/descr | 34 +++ lib/pdp/descr | 38 +++ lib/vax4/descr.src | 37 +++ lib/z80/descr | 31 ++ util/ack/Makefile | 63 ++++ util/ack/ack.h | 88 ++++++ util/ack/data.c | 9 + util/ack/data.h | 43 +++ util/ack/dmach.h | 15 + util/ack/files.c | 94 ++++++ util/ack/grows.c | 79 +++++ util/ack/grows.h | 19 ++ util/ack/list.c | 73 +++++ util/ack/list.h | 23 ++ util/ack/main.c | 340 +++++++++++++++++++++ util/ack/malloc.c | 208 +++++++++++++ util/ack/mktables.c | 121 ++++++++ util/ack/pc/Makefile | 25 ++ util/ack/pc/em_pc.c | 681 +++++++++++++++++++++++++++++++++++++++++++ util/ack/rmach.c | 288 ++++++++++++++++++ util/ack/run.c | 154 ++++++++++ util/ack/scan.c | 244 ++++++++++++++++ util/ack/svars.c | 125 ++++++++ util/ack/trans.c | 672 ++++++++++++++++++++++++++++++++++++++++++ util/ack/trans.h | 30 ++ util/ack/util.c | 190 ++++++++++++ 35 files changed, 4011 insertions(+) create mode 100644 lib/6500/descr create mode 100644 lib/6809/descr create mode 100644 lib/descr/cpm create mode 100644 lib/descr/fe.src create mode 100644 lib/descr/nascom create mode 100644 lib/em22/descr create mode 100644 lib/i80/descr create mode 100644 lib/i86/descr create mode 100644 lib/m68k2/descr create mode 100644 lib/m68k4/descr create mode 100644 lib/pdp/descr create mode 100644 lib/vax4/descr.src create mode 100644 lib/z80/descr create mode 100644 util/ack/Makefile create mode 100644 util/ack/ack.h create mode 100644 util/ack/data.c create mode 100644 util/ack/data.h create mode 100644 util/ack/dmach.h create mode 100644 util/ack/files.c create mode 100644 util/ack/grows.c create mode 100644 util/ack/grows.h create mode 100644 util/ack/list.c create mode 100644 util/ack/list.h create mode 100644 util/ack/main.c create mode 100644 util/ack/malloc.c create mode 100644 util/ack/mktables.c create mode 100644 util/ack/pc/Makefile create mode 100644 util/ack/pc/em_pc.c create mode 100644 util/ack/rmach.c create mode 100644 util/ack/run.c create mode 100644 util/ack/scan.c create mode 100644 util/ack/svars.c create mode 100644 util/ack/trans.c create mode 100644 util/ack/trans.h create mode 100644 util/ack/util.c diff --git a/lib/6500/descr b/lib/6500/descr new file mode 100644 index 000000000..41738ccd4 --- /dev/null +++ b/lib/6500/descr @@ -0,0 +1,27 @@ +var w=2 +var p=2 +var s=2 +var l=4 +var f=4 +var d=8 +var NAME=m6500 +var M=6500 +var LIB=mach/6500/lib/tail_ +var RT=mach/6500/lib/head_ +var INCLUDES=-I{EM}/include +name be + from .m + to .s + program {EM}/lib/{M}_be + args < + prop > + need .e +end +name asld + from .s.a + to a.out + program {EM}/lib/{M}_as + mapflag -l* LNAME={EM}/{LIB}* + args (.e:{HEAD}={EM}/{RT}em) -o > (.e:{TAIL}={EM}/{LIB}em) + prop C +end diff --git a/lib/6809/descr b/lib/6809/descr new file mode 100644 index 000000000..c08ac85a6 --- /dev/null +++ b/lib/6809/descr @@ -0,0 +1,31 @@ +var w=2 +var i=2 +var p=2 +var s=2 +var l=4 +var f=4 +var d=8 +var NAME=m6809 +var M=6809 +var LIB=mach/6809/lib/tail_ +var RT=mach/6809/lib/head_ +var INCLUDES=-I{EM}/include +name be + from .m + to .s + program {EM}/lib/{M}_be + args < + prop > + need .e +end +name asld + from .s.a + to a.out + program {EM}/lib/{M}_as + mapflag -l* LNAME={EM}/{LIB}* + args (.e:{HEAD}={EM}/{RT}em) \ +({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ +(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ +(.c.p:{TAIL}={EM}/{LIB}mon) (.e:{TAIL}={EM}/{LIB}em) + prop C +end diff --git a/lib/descr/cpm b/lib/descr/cpm new file mode 100644 index 000000000..262b12446 --- /dev/null +++ b/lib/descr/cpm @@ -0,0 +1,25 @@ +var w=2 +var p=2 +var s=2 +var l=4 +var f=4 +var d=4 +var M=cpm +var NAME=CPM +var LIB=mach/z80/int/lib/tail_ +var RT=mach/z80/int/lib/head_ +var SIZE_F=-sm +var INCLUDES=-I{EM}/include +name asld + from .k.m.a + to e.out + program {EM}/lib/em_ass + mapflag -l* LNAME={EM}/{LIB}* + mapflag -+* ASS_F={ASS_F?} -+* + mapflag --* ASS_F={ASS_F?} --* + mapflag -s* SIZE_F=-s* + args {ASS_F?} ({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ +(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ +(.c.p:{TAIL}={EM}/{LIB}mon) + prop C +end diff --git a/lib/descr/fe.src b/lib/descr/fe.src new file mode 100644 index 000000000..288d5219a --- /dev/null +++ b/lib/descr/fe.src @@ -0,0 +1,60 @@ +# (c) copyright 1983 by the Vrije Universiteit, Amsterdam, The Netherlands. +name cpp + # no from, it's governed by the P property + to .i + program {EM}/lib/cpp + mapflag -I* CPP_F={CPP_F?} -I* + mapflag -U* CPP_F={CPP_F?} -U* + mapflag -D* CPP_F={CPP_F?} -D* + args {CPP_F?} {INCLUDES?} -D{NAME} -DEM_WSIZE={w} -DEM_PSIZE={p} \ +-DEM_SSIZE={s} -DEM_LSIZE={l} -DEM_FSIZE={f} -DEM_DSIZE={d} < + prop >P +end +name cem + from .c + to .k + program {EM}/lib/em_cem + mapflag -p CEM_F={CEM_F?} -Xp + mapflag -L CEM_F={CEM_F?} -l + args -Vw{w}i{w}p{p}f{f}s{s}l{l}d{d} {CEM_F?} + prop <>p + rts .c + need .c +end +name pc + from .p + to .k + program {EM}/lib/em_pc + mapflag -p PC_F={PC_F?} -p + mapflag -w PC_F={PC_F?} -w + mapflag -E PC_F={PC_F?} -E + mapflag -e PC_F={PC_F?} -e + mapflag -{*} PC_F={PC_F?} -\{*} + mapflag -L PC_F={PC_F?} -\{l-} + args -Vw{w}p{p}f{d}l{l} {PC_F?} < > {SOURCE} + prop m + rts .p + need .p + end + name encode + from .e + to .k + program {EM}/lib/em_encode + args < + prop >m +end +name opt + from .k + to .m + program {EM}/lib/em_opt + mapflag -LIB OPT_F={OPT_F?} -L + args {OPT_F?} < + prop >O +end +name decode + from .k.m + to .e + program {EM}/lib/em_decode + args < + prop > +end diff --git a/lib/descr/nascom b/lib/descr/nascom new file mode 100644 index 000000000..c9a560a6c --- /dev/null +++ b/lib/descr/nascom @@ -0,0 +1,28 @@ +var w=1 +var p=2 +var s=1 +var l=2 +var f=4 +var d=8 +var NAME=nascom +var M=z80a +var LIB=mach/z80a/lib/tail_ +var RT=mach/z80a/lib/head_ +var INCLUDES=-I{EM}/include +name be + from .m + to .s + program {EM}/lib/{M}_be + args < + prop > + need .e +end +name asld + from .s.a + to a.out + program {EM}/lib/{M}_as + mapflag -l* LNAME={EM}/{LIB}* + args (.e:{HEAD}={EM}/{RT}em) ({RTS}:.c={EM}/{RT}cc) -o > \ +(.e:{TAIL}={EM}/{LIB}em.1 {EM}/{LIB}em.2) + prop C +end diff --git a/lib/em22/descr b/lib/em22/descr new file mode 100644 index 000000000..6d897fb15 --- /dev/null +++ b/lib/em22/descr @@ -0,0 +1,27 @@ +var w=2 +var p=2 +var s=2 +var l=4 +var f=4 +var d=8 +var M=int +var NAME=int22 +var LIB=mach/int/lib/tail_ +var RT=mach/int/lib/head_ +var SIZE_FLAG=-sm +var INCLUDES=-I{EM}/include +name asld + from .k.m.a + to e.out + program {EM}/lib/em_ass + mapflag -l* LNAME={EM}/{LIB}* + mapflag -+* ASS_F={ASS_F?} -+* + mapflag --* ASS_F={ASS_F?} --* + mapflag -s* SIZE_FLAG=-s* + args {SIZE_FLAG} \ + ({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ + (.p:{TAIL}={EM}/{LIB}pc) \ + (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ + (.c.p:{TAIL}={EM}/{LIB}mon) + prop C +end diff --git a/lib/i80/descr b/lib/i80/descr new file mode 100644 index 000000000..2b31a593e --- /dev/null +++ b/lib/i80/descr @@ -0,0 +1,27 @@ +var w=2 +var p=2 +var s=2 +var l=4 +var f=4 +var d=8 +var NAME=i8080 +var M=8080 +var LIB=mach/8080/lib/tail_ +var RT=mach/8080/lib/head_ +var INCLUDES=-I{EM}/include +name be + from .m + to .s + program {EM}/lib/{M}_be + args < + prop > + need .e +end +name asld + from .s.a + to a.out + program {EM}/lib/{M}_as + mapflag -l* LNAME={EM}/{LIB}* + args ({RTS}:.c={EM}/{RT}cc) -o > < + prop C +end diff --git a/lib/i86/descr b/lib/i86/descr new file mode 100644 index 000000000..7135e9f71 --- /dev/null +++ b/lib/i86/descr @@ -0,0 +1,32 @@ +var w=2 +var p=2 +var s=2 +var l=4 +var f=4 +var d=8 +var NAME=i8086 +var M=i86 +var LIB=mach/i86/lib/tail_ +var RT=mach/i86/lib/head_ +var INCLUDES=-I{EM}/include +name be + from .m + to .s + program {EM}/lib/{M}_cg + args < + prop > + need .e +end +name asld + from .s.a + to a.out + program {EM}/lib/{M}_as + mapflag -l* LNAME={EM}/{LIB}* + mapflag -i IFILE={EM}/{RT}i + args {IFILE?} (.e:{HEAD}={EM}/{RT}em) \ +({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ +(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ +(.c.p.e:{TAIL}={EM}/{LIB}alo) (.c.p:{TAIL}={EM}/{LIB}mon) \ +(.e:{TAIL}={EM}/{LIB}em) + prop C +end diff --git a/lib/m68k2/descr b/lib/m68k2/descr new file mode 100644 index 000000000..7cd66069e --- /dev/null +++ b/lib/m68k2/descr @@ -0,0 +1,30 @@ +var w=2 +var p=4 +var s=2 +var l=4 +var f=4 +var d=8 +var NAME=m68k2 +var M=m68k2 +var LIB=mach/m68k2/lib/tail_ +var RT=mach/m68k2/lib/head_ +var INCLUDES=-I{EM}/include +name be + from .m + to .s + program {EM}/lib/{M}_cg + args < + prop > + need .e +end +name asld + from .s.a + to a.out + program {EM}/lib/{M}_as + mapflag -l* LNAME={EM}/{LIB}* + args (.e:{HEAD}={EM}/{RT}em) \ +({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ +(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ +(.e:{TAIL}={EM}/{LIB}em.rt {EM}/{LIB}mon {EM}/{LIB}em.vend) + prop Cm +end diff --git a/lib/m68k4/descr b/lib/m68k4/descr new file mode 100644 index 000000000..16f1f4904 --- /dev/null +++ b/lib/m68k4/descr @@ -0,0 +1,34 @@ +var w=4 +var p=4 +var s=2 +var l=4 +var f=4 +var d=8 +var NAME=m68k4 +var M=m68k4 +var LIBDIR=mach/m68k4/lib +var LIB=mach/m68k4/lib/tail_ +var RT=mach/m68k4/lib/head_ +var INCLUDES=-I{EM}/include +name be + from .m + to .s + program {EM}/lib/{M}_cg + args < + prop > + need .e +end +name asld + from .s.a + to a.out + program {EM}/lib/{M}_as + mapflag -l* LNAME={EM}/{LIB}* + args (.e:{HEAD}={EM}/{RT}em) \ +({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ +(.p.c:{TAIL}={EM}/{LIBDIR}/sys1.s) (.p:{TAIL}={EM}/{LIBDIR}/sys2.s) \ +(.c:{TAIL}={EM}/{LIBDIR}/write.s) \ +(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ +(.c:{TAIL}={EM}/{LIB}mon {EM}/{LIB}fake) \ +(.e:{TAIL}={EM}/{LIB}em.rt {EM}/{LIB}em.vend) + prop Cm +end diff --git a/lib/pdp/descr b/lib/pdp/descr new file mode 100644 index 000000000..3a90a8b9d --- /dev/null +++ b/lib/pdp/descr @@ -0,0 +1,38 @@ +var w=2 +var p=2 +var s=2 +var l=4 +var f=4 +var d=8 +var M=pdp +var NAME=pdp +var LIB=mach/pdp/lib/tail_ +var RT=mach/pdp/lib/head_ +var INCLUDES=-I{EM}/include +name be + from .m + to .s + program {EM}/lib/{M}_cg + args < + prop > + need .e +end +name as + from .s + to .o + program /bin/as + args - -o > < + prop m +end +name ld + from .o.a + to a.out + program /bin/ld + mapflag -l* LNAME={EM}/{LIB}* + args (.e:{HEAD}={EM}/{RT}em) \ + ({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ + (.p:{TAIL}={EM}/{LIB}pc) \ + (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ + (.e:{TAIL}={EM}/{LIB}em) (.c.p:{TAIL}=/lib/libc.a) + prop C +end diff --git a/lib/vax4/descr.src b/lib/vax4/descr.src new file mode 100644 index 000000000..f9c1e5e3a --- /dev/null +++ b/lib/vax4/descr.src @@ -0,0 +1,37 @@ +var w=4 +var p=4 +var s=2 +var l=4 +var f=4 +var d=8 +var M=vax4 +var NAME=vax4 +var LIB=mach/vax4/lib/tail_ +var RT=mach/vax4/lib/head_ +var INCLUDES=-I{EM}/include +name be + from .m + to .s + program {EM}/lib/{M}_cg + args < + prop > + need .e +end +name as + from .s + to .o + program /bin/as + args - -o > < + prop m +end +name ld + from .o.a + to a.out + program /bin/ld + mapflag -l* LNAME={EM}/{LIB}* + args (.e:{HEAD}={EM}/{RT}em) \ +({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ +(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ +(.e:{TAIL}={EM}/{LIB}em) (.c.p:{TAIL}={EM}/{LIB}mon) + prop C +end diff --git a/lib/z80/descr b/lib/z80/descr new file mode 100644 index 000000000..f201f983b --- /dev/null +++ b/lib/z80/descr @@ -0,0 +1,31 @@ +var w=2 +var p=2 +var s=2 +var l=4 +var f=4 +var d=8 +var NAME=z80 +var M=z80 +var LIB=mach/z80/lib/tail_ +var RT=mach/z80/lib/head_ +var INCLUDES=-I{EM}/include +name be + from .m + to .s + program {EM}/lib/{M}_cg + args < + prop > + need .e +end +name asld + from .s.a + to a.out + program {EM}/lib/{M}_as + mapflag -l* LNAME={EM}/{LIB}* + args (.e:{HEAD}={EM}/{RT}em) \ +({RTS}:.c={EM}/{RT}cc) ({RTS}:.p={EM}/{RT}pc) -o > < \ +(.p:{TAIL}={EM}/{LIB}pc) (.c:{TAIL}={EM}/{LIB}cc.1s {EM}/{LIB}cc.2g) \ +(.c.p.e:{TAIL}={EM}/{LIB}alo) (.c.p:{TAIL}={EM}/{LIB}mon) \ +(.e:{TAIL}={EM}/{LIB}em.vend) + prop C +end diff --git a/util/ack/Makefile b/util/ack/Makefile new file mode 100644 index 000000000..3b985e7d2 --- /dev/null +++ b/util/ack/Makefile @@ -0,0 +1,63 @@ +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) diff --git a/util/ack/ack.h b/util/ack/ack.h new file mode 100644 index 000000000..b084a647b --- /dev/null +++ b/util/ack/ack.h @@ -0,0 +1,88 @@ +/****************************************************************************/ +/* 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 diff --git a/util/ack/data.c b/util/ack/data.c new file mode 100644 index 000000000..b92fc8bd8 --- /dev/null +++ b/util/ack/data.c @@ -0,0 +1,9 @@ +#include "ack.h" +#include "list.h" +#include "trans.h" + + +#undef EXTERN +#define EXTERN + +#include "data.h" diff --git a/util/ack/data.h b/util/ack/data.h new file mode 100644 index 000000000..23af80c5c --- /dev/null +++ b/util/ack/data.h @@ -0,0 +1,43 @@ +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 */ diff --git a/util/ack/dmach.h b/util/ack/dmach.h new file mode 100644 index 000000000..1e7880ada --- /dev/null +++ b/util/ack/dmach.h @@ -0,0 +1,15 @@ +/***************************************************************/ +/* */ +/* 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[] ; diff --git a/util/ack/files.c b/util/ack/files.c new file mode 100644 index 000000000..83f14cd90 --- /dev/null +++ b/util/ack/files.c @@ -0,0 +1,94 @@ +/* + * (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 ; + } +} diff --git a/util/ack/grows.c b/util/ack/grows.c new file mode 100644 index 000000000..0b870e003 --- /dev/null +++ b/util/ack/grows.c @@ -0,0 +1,79 @@ +/* + * (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 ; +} diff --git a/util/ack/grows.h b/util/ack/grows.h new file mode 100644 index 000000000..9e7d55c12 --- /dev/null +++ b/util/ack/grows.h @@ -0,0 +1,19 @@ +/* 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 */ diff --git a/util/ack/list.c b/util/ack/list.c new file mode 100644 index 000000000..fb28fd2ad --- /dev/null +++ b/util/ack/list.c @@ -0,0 +1,73 @@ +/* + * (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 ; +} diff --git a/util/ack/list.h b/util/ack/list.h new file mode 100644 index 000000000..d39aea4c1 --- /dev/null +++ b/util/ack/list.h @@ -0,0 +1,23 @@ +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) ) diff --git a/util/ack/main.c b/util/ack/main.c new file mode 100644 index 000000000..46292ceb3 --- /dev/null +++ b/util/ack/main.c @@ -0,0 +1,340 @@ +/* + * (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 + +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 ) { + 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("Incomplete internal specification for %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 ; + } +} diff --git a/util/ack/malloc.c b/util/ack/malloc.c new file mode 100644 index 000000000..b9ec3df2c --- /dev/null +++ b/util/ack/malloc.c @@ -0,0 +1,208 @@ +/* + * (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&&qptr = 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=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 diff --git a/util/ack/mktables.c b/util/ack/mktables.c new file mode 100644 index 000000000..fffaa038d --- /dev/null +++ b/util/ack/mktables.c @@ -0,0 +1,121 @@ +/* + * (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 +#include + +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 ; i2) ; + 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) ; +} diff --git a/util/ack/pc/Makefile b/util/ack/pc/Makefile new file mode 100644 index 000000000..9089e908a --- /dev/null +++ b/util/ack/pc/Makefile @@ -0,0 +1,25 @@ +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 + +opr: + make pr ^ opr + +pr: + pr -n em_pc.c diff --git a/util/ack/pc/em_pc.c b/util/ack/pc/em_pc.c new file mode 100644 index 000000000..16a138298 --- /dev/null +++ b/util/ack/pc/em_pc.c @@ -0,0 +1,681 @@ +/* + * (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 +#include +#include +#include +#include +#include +#include + +#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 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, %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(); +} diff --git a/util/ack/rmach.c b/util/ack/rmach.c new file mode 100644 index 000000000..7a97bca40 --- /dev/null +++ b/util/ack/rmach.c @@ -0,0 +1,288 @@ +/* + * (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 + +/************************************************************************/ +/* */ +/* 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 ; + gr_cat(&rline,ACK_DIR); gr_cat(&rline,"/") ; + gr_cat(&rline,name) ; + infile= fopen(gr_start(rline),"r") ; + if ( !infile ) { + infile= fopen(name,"r") ; + } + if ( infile==NULL ) { + fuerror("Cannot find description for %s",name) ; + } +} + +close_in() { + if ( !incore ) fclose(infile) ; + gr_throw(&rline) ; +} + +char *readline() { + /* Get a line from the input, + return 0 if at end, + The line is stored in a volatile buffer, + a pointer to the line is returned. + */ + register int nchar ; + enum { BOL, ESCAPE, SKIPPING, MOL } state = BOL ; + + gr_throw(&rline) ; + for (;;) { + nchar= getinchar() ; + if ( nchar==EOF ) { + if ( state!=BOL ) { + werror("incomplete line in %s", inname) ; + } + return 0 ; + } + if ( state==SKIPPING ) { + if ( nchar=='\n' ) { + state= MOL ; + } else { + continue ; + } + } + if ( state==ESCAPE ) { + switch( nchar ) { + case '\n' : + break ; + default : + gr_add(&rline,BSLASH) ; + case COMMENT : + case BSLASH : + gr_add(&rline,nchar) ; + break ; + } + state= MOL ; + continue ; + } + switch ( nchar ) { + case '\n' : gr_add(&rline,0) ; + return gr_start(rline) ; + case COMMENT : state= SKIPPING ; + break ; + case BSLASH : state= ESCAPE ; + break ; + default : gr_add(&rline,nchar) ; + state= MOL ; + } + } +} + +int getinchar() { + 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 ; +} diff --git a/util/ack/run.c b/util/ack/run.c new file mode 100644 index 000000000..a55c759f9 --- /dev/null +++ b/util/ack/run.c @@ -0,0 +1,154 @@ +/* + * (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 + +#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 ; +} diff --git a/util/ack/scan.c b/util/ack/scan.c new file mode 100644 index 000000000..63a5b7c1a --- /dev/null +++ b/util/ack/scan.c @@ -0,0 +1,244 @@ +/* + * (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_ocountocount ) ) ) { + /* 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") ; +} diff --git a/util/ack/svars.c b/util/ack/svars.c new file mode 100644 index 000000000..4749fe1ef --- /dev/null +++ b/util/ack/svars.c @@ -0,0 +1,125 @@ +/* + * (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 ; +} diff --git a/util/ack/trans.c b/util/ack/trans.c new file mode 100644 index 000000000..3eeab9841 --- /dev/null +++ b/util/ack/trans.c @@ -0,0 +1,672 @@ +/* + * (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 && eqt_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 && nct_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) ; +} diff --git a/util/ack/trans.h b/util/ack/trans.h new file mode 100644 index 000000000..7e305d605 --- /dev/null +++ b/util/ack/trans.h @@ -0,0 +1,30 @@ +/* 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)) diff --git a/util/ack/util.c b/util/ack/util.c new file mode 100644 index 000000000..ac32f38ca --- /dev/null +++ b/util/ack/util.c @@ -0,0 +1,190 @@ +/* + * (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 +#include + +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 ; +}