Initial revision
authorkeie <none@none>
Thu, 21 Jun 1984 10:57:59 +0000 (10:57 +0000)
committerkeie <none@none>
Thu, 21 Jun 1984 10:57:59 +0000 (10:57 +0000)
35 files changed:
lib/6500/descr [new file with mode: 0644]
lib/6809/descr [new file with mode: 0644]
lib/descr/cpm [new file with mode: 0644]
lib/descr/fe.src [new file with mode: 0644]
lib/descr/nascom [new file with mode: 0644]
lib/em22/descr [new file with mode: 0644]
lib/i80/descr [new file with mode: 0644]
lib/i86/descr [new file with mode: 0644]
lib/m68k2/descr [new file with mode: 0644]
lib/m68k4/descr [new file with mode: 0644]
lib/pdp/descr [new file with mode: 0644]
lib/vax4/descr.src [new file with mode: 0644]
lib/z80/descr [new file with mode: 0644]
util/ack/Makefile [new file with mode: 0644]
util/ack/ack.h [new file with mode: 0644]
util/ack/data.c [new file with mode: 0644]
util/ack/data.h [new file with mode: 0644]
util/ack/dmach.h [new file with mode: 0644]
util/ack/files.c [new file with mode: 0644]
util/ack/grows.c [new file with mode: 0644]
util/ack/grows.h [new file with mode: 0644]
util/ack/list.c [new file with mode: 0644]
util/ack/list.h [new file with mode: 0644]
util/ack/main.c [new file with mode: 0644]
util/ack/malloc.c [new file with mode: 0644]
util/ack/mktables.c [new file with mode: 0644]
util/ack/pc/Makefile [new file with mode: 0644]
util/ack/pc/em_pc.c [new file with mode: 0644]
util/ack/rmach.c [new file with mode: 0644]
util/ack/run.c [new file with mode: 0644]
util/ack/scan.c [new file with mode: 0644]
util/ack/svars.c [new file with mode: 0644]
util/ack/trans.c [new file with mode: 0644]
util/ack/trans.h [new file with mode: 0644]
util/ack/util.c [new file with mode: 0644]

diff --git a/lib/6500/descr b/lib/6500/descr
new file mode 100644 (file)
index 0000000..41738cc
--- /dev/null
@@ -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 (file)
index 0000000..c08ac85
--- /dev/null
@@ -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 (file)
index 0000000..262b124
--- /dev/null
@@ -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 (file)
index 0000000..288d521
--- /dev/null
@@ -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 (file)
index 0000000..c9a560a
--- /dev/null
@@ -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 (file)
index 0000000..6d897fb
--- /dev/null
@@ -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 (file)
index 0000000..2b31a59
--- /dev/null
@@ -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 (file)
index 0000000..7135e9f
--- /dev/null
@@ -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 (file)
index 0000000..7cd6606
--- /dev/null
@@ -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 (file)
index 0000000..16f1f49
--- /dev/null
@@ -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 (file)
index 0000000..3a90a8b
--- /dev/null
@@ -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 (file)
index 0000000..f9c1e5e
--- /dev/null
@@ -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 (file)
index 0000000..f201f98
--- /dev/null
@@ -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 (file)
index 0000000..3b985e7
--- /dev/null
@@ -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 (file)
index 0000000..b084a64
--- /dev/null
@@ -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 (file)
index 0000000..b92fc8b
--- /dev/null
@@ -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 (file)
index 0000000..23af80c
--- /dev/null
@@ -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 (file)
index 0000000..1e7880a
--- /dev/null
@@ -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 (file)
index 0000000..83f14cd
--- /dev/null
@@ -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 (file)
index 0000000..0b870e0
--- /dev/null
@@ -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 (file)
index 0000000..9e7d55c
--- /dev/null
@@ -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 (file)
index 0000000..fb28fd2
--- /dev/null
@@ -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 (file)
index 0000000..d39aea4
--- /dev/null
@@ -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 (file)
index 0000000..46292ce
--- /dev/null
@@ -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 <signal.h>
+
+static int sigs[] = { SIGINT, SIGHUP, SIGTERM, 0 } ;
+
+extern  char    *getenv();
+
+main(argc,argv) char **argv ; {
+       register list_elem *elem ;
+       register char *frontend ;
+       register int *n_sig ;
+
+       progname=argv[0];
+       varinit();
+       vieuwargs(argc,argv);
+       if ( (frontend=getenv("ACKFE")) ) {
+               setlist(frontend) ;
+       } else {
+               setlist(FRONTENDS);
+       }
+       setlist(machine);
+       transini();
+       scanneeds();
+       template= mktemp(ACKNAME) ;
+       if ( n_error && !k_flag ) return n_error ;
+
+       for ( n_sig=sigs ; *n_sig ; n_sig++ ) {
+               if ( signal(*n_sig,noodstop)==SIG_IGN ) {
+                       signal(*n_sig,SIG_IGN) ;
+               }
+       }
+       scanlist ( l_first(arguments), elem ) {
+               if ( !process(l_content(*elem)) && !k_flag ) return 1 ;
+       }
+       orig.p_path= (char *)0 ;
+
+       if ( !combiner && !stopsuffix ) {
+               /* Call combiner directly without any transformation */
+               scanlist(l_first(tr_list),elem) {
+                       if ( t_cont(*elem)->t_combine ) {
+                               combiner= t_cont(*elem) ;
+                       }
+               }
+       }
+
+       if ( !combiner || n_error ) return n_error ;
+
+       if ( !do_combine() ) return 1 ;
+
+       if ( g_flag ) {
+               return do_run();
+       }
+
+       return 0 ;
+}
+
+char *srcvar() {
+       return orig.p_path ;
+}
+
+varinit() {
+       /* initialize the string variables */
+       setsvar(keeps(HOME),keeps(EM_DIR)) ;
+       setpvar(keeps(SRC),srcvar)  ;
+}
+
+/************************* flag processing ***********************/
+
+vieuwargs(argc,argv) char **argv ; {
+       register char *argp;
+       register int nextarg ;
+       register int eaten ;
+
+       firstarg(argv[0]) ;
+
+       nextarg= 1 ;
+
+       while ( nextarg<argc ) {
+               argp= argv[nextarg] ;
+               nextarg++ ;
+               if ( argp[0]!='-' || argp[1]=='l' ) {
+                       /* Not a flag, or a library */
+                       l_add(&arguments,argp) ;
+                       continue ;
+               }
+
+               /* Flags */
+               eaten=0 ; /* Did not 'eat' tail of flag yet */
+               switch ( argp[1] ) {
+          case 'm':    if ( machine ) fuerror("Two machines?") ;
+                       machine= &argp[2];
+                       eaten=1 ;
+                       break ;
+          case 'o':    if ( nextarg>=argc ) {
+                               fuerror("-o can't be the last flag") ;
+                       }
+                       if ( outfile ) fuerror("Two results?") ;
+                       outfile= argv[nextarg++] ;
+                       break ;
+          case 'O':    Optflag++ ;
+                       break ;
+          case 'v':    v_flag++ ;
+                       break ;
+          case 'g':    g_flag++ ;
+                       break ;
+          case 'c':    if ( stopsuffix ) fuerror("Two -c flags") ;
+                       stopsuffix= &argp[2]; eaten=1;
+                       if ( *stopsuffix && *stopsuffix!=SUFCHAR ) {
+                               fuerror("-c flag has invalid tail") ;
+                       }
+                       break ;
+          case 'k':    k_flag++ ;
+                       break ;
+          case 't':    t_flag++ ;
+                       break ;
+          case 'R':    do_Rflag(argp); eaten=1;
+                       break ;
+          case 'r':    if ( argp[2]!=SUFCHAR ) {
+                               error("-r must be followed by %c",SUFCHAR) ;
+                       }
+                       keeptail(&argp[2]); eaten=1 ;
+                       break ;
+          case '.':    if ( rts ) fuerror("Two run-time systems?") ;
+                       rts= &argp[1] ; eaten=1;
+                       keephead(rts) ; keeptail(rts) ;
+                       break ;
+#ifdef DEBUG
+          case 'd':    debug++ ;
+                       break ;
+#endif
+          case  0 :    nill_flag++ ; eaten++ ;
+                       break;
+          case 'w':    { register char *tokeep ;
+                         w_flag++;
+                         tokeep=keeps(argp) ;
+                         *tokeep |= NO_SCAN ;
+                         l_add(&flags,tokeep) ;
+                       }
+                       break ;
+          default:     /* The flag is not recognized,
+                          put it on the list for the sub-processes
+                       */
+#ifdef DEBUG
+                       if ( debug ) {
+                               vprint("Flag %s: phase dependent\n",argp) ;
+                       }
+#endif
+                       l_add(&flags,keeps(argp)) ;
+                       eaten=1 ;
+               }
+               if ( argp[2] && !eaten ) {
+                       werror("Unexpected characters at end of %s",argp) ;
+               }
+       }
+       if ( !machine && ! (machine=getenv("ACKM")) ) {
+#ifdef ACKM
+               machine= ACKM;          /* The default machine */
+#else
+               fuerror("No machine specified") ;
+#endif
+       }
+       return ;
+}
+
+firstarg(argp) register char *argp ; {
+       register char *name ;
+
+       name=rindex(argp,'/') ;
+       if ( name && *(name+1) ) {
+               name++ ;
+       } else {
+               name= argp ;
+       }
+       if ( strcmp(name,"ack")==0 ) return ;
+       if ( strcmp(name,"acc")==0 || strcmp(name,"cc")==0 ) {
+               rts= ".c" ; keephead(rts) ; keeptail(rts) ;
+               return ;
+       }
+       if ( strcmp(name,"apc")==0 || strcmp(name,"pc")==0 ) {
+               rts= ".p" ; keephead(rts) ; keeptail(rts) ;
+               return ;
+       }
+       machine= name;
+}
+
+/************************* argument processing ***********************/
+
+process(arg) char *arg ; {
+       /* Process files & library arguments */
+       register list_elem *elem ;
+       register trf *phase ;
+       int first=YES ;
+
+#ifdef DEBUG
+       if ( debug ) vprint("Processing %s\n",arg) ;
+#endif
+       if ( arg[0]=='-' ) { l_add(&c_arguments,keeps(arg)) ; return 1 ; }
+       p_suffix= rindex(arg,SUFCHAR) ;
+       if ( p_basename ) throws(p_basename) ;
+       orig.p_keep= YES ;      /* Don't throw away the original ! */
+       orig.p_path= arg ;
+       p_basename= keeps(basename(arg)) ;
+       if ( !p_suffix ) { l_add(&c_arguments,keeps(arg)) ; return 1 ; }
+       /* Try to find a path through the transformations */
+       switch( setpath() ) {
+       case F_NOPATH :
+               error("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 (file)
index 0000000..b9ec3df
--- /dev/null
@@ -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&&q<alloct);
+                                       p->ptr = q->ptr;
+                               }
+                               if(q>=p+nw && p+nw>=p)
+                                       goto found;
+                       }
+                       q = p;
+                       p = clearbusy(p->ptr);
+                       if(p>q)
+                               ASSERT(p<=alloct);
+                       else if(q!=alloct || p!=allocs) {
+                               ASSERT(q==alloct&&p==allocs);
+                               return(NULL);
+                       } else if(++temp>1)
+                               break;
+               }
+               temp = ((nw+BLOCK/WORD)/(BLOCK/WORD))*(BLOCK/WORD);
+               q = (union store *)sbrk(0);
+               if(q+temp+GRANULE < q) {
+                       return(NULL);
+               }
+               q = (union store *)sbrk(temp*WORD);
+               if((INT)q == -1) {
+                       return(NULL);
+               }
+               ASSERT(q>alloct);
+               alloct->ptr = q;
+               if(q!=alloct+1)
+                       alloct->ptr = setbusy(alloct->ptr);
+               alloct = q->ptr = q+temp-1;
+               alloct->ptr = setbusy(allocs);
+       }
+found:
+       allocp = p + nw;
+       ASSERT(allocp<=alloct);
+       if(q>allocp) {
+               allocx = allocp->ptr;
+               allocp->ptr = p->ptr;
+       }
+       p->ptr = setbusy(allocp);
+       return((char *)(p+1));
+}
+
+/*      freeing strategy tuned for LIFO allocation
+*/
+free(ap)
+register char *ap;
+{
+       register union store *p = (union store *)ap;
+
+       ASSERT(p>clearbusy(allocs[1].ptr)&&p<=alloct);
+       ASSERT(allock());
+       allocp = --p;
+       ASSERT(testbusy(p->ptr));
+       p->ptr = clearbusy(p->ptr);
+       ASSERT(p->ptr > allocp && p->ptr <= alloct);
+}
+
+/*      realloc(p, nbytes) reallocates a block obtained from malloc()
+ *      and freed since last call of malloc()
+ *      to have new size nbytes, and old content
+ *      returns new location, or 0 on failure
+*/
+
+char *
+realloc(p, nbytes)
+register union store *p;
+unsigned nbytes;
+{
+       register union store *q;
+       union store *s, *t;
+       register unsigned nw;
+       unsigned onw;
+
+       if(testbusy(p[-1].ptr))
+               free((char *)p);
+       onw = p[-1].ptr - p;
+       q = (union store *)malloc(nbytes);
+       if(q==NULL || q==p)
+               return((char *)q);
+       s = p;
+       t = q;
+       nw = (nbytes+WORD-1)/WORD;
+       if(nw<onw)
+               onw = nw;
+       while(onw--!=0)
+               *t++ = *s++;
+       if(q<p && q+nw>=p)
+               (q+(q+nw-p))->ptr = allocx;
+       return((char *)q);
+}
+
+#ifdef DEBUG
+allock()
+{
+#ifdef DEBUG
+       register union store *p;
+       int x;
+       x = 0;
+       for(p= &allocs[0]; clearbusy(p->ptr) > p; p=clearbusy(p->ptr)) {
+               if(p==allocp)
+                       x++;
+       }
+       ASSERT(p==alloct);
+       return(x==1|p==allocp);
+#else
+       return(1);
+#endif
+}
+#endif
diff --git a/util/ack/mktables.c b/util/ack/mktables.c
new file mode 100644 (file)
index 0000000..fffaa03
--- /dev/null
@@ -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 <stdio.h>
+#include <ctype.h>
+
+char *fname = 0 ;
+char dname[200] ;
+char *tail ;
+
+FILE *intab ;
+FILE *dmach ;
+
+int index ;
+
+main(argc,argv) char **argv ; {
+       register i ;
+
+       start(argv[1]) ;
+       for ( i=2 ; i<argc ; i++ ) {
+               fname= argv[i] ;
+               readm() ;
+       }
+       stop(argc>2) ;
+       return 0 ;
+}
+
+start(dir) char *dir ; {
+       tail= dname ;
+       while ( *dir ) {
+               *tail++ = *dir ++ ;
+       }
+       if ( tail!=dname ) *tail++= '/' ;
+       index=0 ;
+       intab= fopen("intable.c","w");
+       dmach= fopen("dmach.c","w");
+       if ( intab==NULL || dmach==NULL ) {
+               fprintf(stderr,"Couln't create output file(s)\n");
+               exit ( 1) ;
+       }
+       fprintf(dmach,"#include \"dmach.h\"\n\ndmach\tmassoc[] = {\n") ;
+       fprintf(intab,"char intable[] = {\n") ;
+}
+
+stop(filled) {
+       fprintf(dmach,"\t{\"\",\t-1\t}\n} ;\n") ;
+       if ( !filled ) fprintf(intab,"\t0\n") ;
+       fprintf(intab,"\n} ;\n") ;
+       fclose(dmach); fclose(intab) ;
+}
+
+FILE *do_open(file) char *file ; {
+       strcpy(tail,file) ;
+       return fopen(dname,"r") ;
+}
+
+readm() {
+       register int i ;
+       register int token ;
+       register FILE *in ;
+
+       in=do_open(fname) ;
+       if ( in==NULL ) {
+               fprintf(stderr,"Cannot open %s\n",fname) ;
+               return ;
+       }
+       i=0 ;
+       fprintf(dmach,"\t{\"%s\",\t%d\t},\n",fname,index) ;
+       fprintf(intab,"\n/* %s */\n\t",fname) ;
+       for (;;) {
+               token=getc(in) ;
+               index++ ;
+               if ( ++i == 10 ) {
+                       fprintf(intab,"\n\t") ;
+                       i=0 ;
+               } else {
+                       fprintf(intab," ") ;
+               }
+               if ( !isascii(token) || !(isprint(token) || isspace(token)) ){
+                       if ( token!=EOF ) {
+                         fprintf(stderr,"warning: non-ascii in %s\n",fname) ;
+                         fprintf(intab,"%4d,",token) ;
+                       } else {
+                         fprintf(intab,"  0,",token) ;
+                         break ;
+                       }
+               } else if ( isprint(token) ) {
+                       switch ( token ) {
+                       case '\'': fprintf(intab,"'\\''") ; break ;
+                       case '\\': fprintf(intab,"'\\\\'") ; break ;
+                       default:   fprintf(intab," '%c'",token) ; break ;
+                       }
+               } else switch ( token ) {
+               case '\n' : fprintf(intab,"'\\n'") ; break ;
+               case '\t' : fprintf(intab,"'\\t'") ; break ;
+               case '\r' : fprintf(intab,"'\\r'") ; break ;
+               case '\f' : fprintf(intab,"'\\f'") ; break ;
+               case ' '  : fprintf(intab," ' '")  ; break ;
+               default :   fprintf(stderr,"warning: unrec. %d\n",
+                               token) ;
+                           fprintf(intab,"%4d",token) ;
+                           break ;
+               }
+               fprintf(intab,",") ;
+       }
+       fclose(in) ;
+}
diff --git a/util/ack/pc/Makefile b/util/ack/pc/Makefile
new file mode 100644 (file)
index 0000000..9089e90
--- /dev/null
@@ -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 (file)
index 0000000..16a1382
--- /dev/null
@@ -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        <stdio.h>
+#include        <signal.h>
+#include        <sys/types.h>
+#include        <sys/dir.h>
+#include        <em_path.h>
+#include        <pc_size.h>
+#include        <local.h>
+
+#define        MAX_FLAG                40      /* The Max. no of '{' flags allowed */
+
+#define void                    int
+
+char   *pc_path        =       PEM_PATH ;
+char    *err_path       =      ERR_PATH;
+
+int     toterr;
+int     parent;
+
+char    *eeflag;
+char    *vvflag = "-V";
+int    no_pemflag = 0 ;
+char    *pemflag[MAX_FLAG];
+char    *eflag;
+char    *wflag;
+
+int     sizes[sz_last+1] = {
+       2,      /* sz_addr */
+       8,      /* sz_real */
+       0,      /* sz_head */
+       512,    /* sz_buff */
+       4096,   /* sz_mset */
+       2,      /* sz_iset */
+};
+
+#define CALLSIZE                60
+char    *callvector[CALLSIZE];
+char    **av;
+int     ac;
+int     fileargs;               /* number of recognized, processed args */
+int     flagargs;
+char    *progname;
+char    *source;
+
+#define CHARSIZE                2500
+#define CHARMARG                50
+char    charbuf[CHARSIZE];
+char    *charp                  = charbuf;
+
+char    *tmp_dir                = TMP_DIR;
+char    *unique                 = "pcXXXXXX";
+
+char    sigs[] = {
+       SIGHUP,
+       SIGINT,
+       SIGTERM,
+       0
+};
+
+/*
+ * forward function declarations
+ */
+void    finish();
+void    pem();
+int     list();
+char    *flag();
+char    *tempfile();
+char    **initvector();
+char    *basename();
+
+/*
+ * used library routines and data
+ */
+
+extern  char    *sys_errlist[];
+extern  int     errno;
+
+int     atoi();
+void    exit();
+void    sleep();
+void    execv();
+char    *sbrk();
+int     chdir();
+int     fork();
+int     wait();
+int     getpid();
+int     open();
+int     close();
+int     read();
+
+main(argc,argv) char **argv; {
+       register char *p;
+       char *files[3] ;
+
+       for (p = sigs; *p; p++)
+               if (signal(*p,finish) == SIG_IGN)
+                       signal(*p,SIG_IGN);
+       ac = argc;
+       av = argv;
+       progname = *av++;
+       init();
+       while ( --ac>0 ) {
+               p = *av++;
+               if (*p == '-') {
+                       flagargs++;
+                       p = flag(p);
+               } else {
+                       if ( fileargs>=3 ) fatal("Too many file arguments") ;
+                       files[fileargs++]= p;
+               }
+       }
+       if ( fileargs!=3 ) fatal("Not enough arguments") ;
+       source=files[2] ;
+       pem(files[0],files[1]) ;
+       finish();
+}
+
+char *flag(f) char *f; {
+       register char *p;
+
+       p = f+1;
+       switch (*p++) {
+       case 'e':
+               eflag = f;
+               break;
+       case 'E':
+               eeflag = f;
+               break;
+       case 'w':
+               wflag = f;
+               break;
+       case 'V':
+               vvflag = f;
+               return(0);
+       case '{':
+               if ( no_pemflag>=MAX_FLAG ) {
+                       ermess("too many flags, ignored %s",f) ;
+               } else {
+                       pemflag[no_pemflag++] = p;
+               }
+               return(0);
+       case 'R':
+               pc_path= p ;
+               return 0 ;
+       case 'r' :
+               err_path= p ;
+               return 0 ;
+       default:
+               return(f);
+       }
+       if (*p)
+               fatal("bad flag %s",f);
+       return(0);
+}
+
+initsizes(f) FILE *f; {
+       register c, i;
+       register char *p;
+
+       p = vvflag + 2;
+       while (c = *p++) {
+               i = atoi(p);
+               while (*p >= '0' && *p <= '9')
+                       p++;
+               switch (c) {
+               case 'p': sz_addr = i; continue;
+               case 'f': sz_real = i; continue;
+               case 'h': sz_head = i; continue;
+               case 'b': sz_buff = i; continue;
+               case 'm': sz_mset = i; continue;
+               case 'j': sz_iset = i; continue;
+               case 'w':
+               case 'i': if (i == 2) continue; break;
+               case 'l': if (i == 4) continue; break;
+               }
+               fatal("bad V-flag %s",vvflag);
+       }
+       if (sz_head == 0)
+               sz_head = 6*sz_word + 2*sz_addr;
+       for (i = 0; i <= sz_last; i++)
+               fprintf(f, "%d\n",sizes[i]);
+}
+
+/* ------------------ calling sequences -------------------- */
+
+pem(p,q) char *p,*q; {
+       register char **v,*d;
+       int i;
+       FILE *erfil;
+
+       v = initvector(pc_path);
+       d = tempfile('d');
+       if ((erfil = fopen(d,"w")) == NULL)
+               syserr(d);
+       initsizes(erfil);
+       fprintf(erfil,"%s\n",basename(source));
+       for ( i=0 ; i<no_pemflag ; i++ ) fprintf(erfil,"%s\n",pemflag[i]);
+       fclose(erfil);
+       *v++ = q;
+       *v++ = d;
+       call(v,p,(char *)0);
+       if (toterr == 0)
+               if (list(p,d) < 0)
+                       toterr++;
+       donewith(d);
+}
+
+/* ------------------- miscellaneous routines --------------- */
+
+char *basename(p) char *p; {
+       register char *q;
+
+       q = p;
+       while (*q)
+               if (*q++ == '/')
+                       p = q;
+       return(p);
+}
+
+char *tempfile(suf) {
+       register char *p,*q;
+       register i;
+
+       p = charp; q = tmp_dir;
+       while (*p = *q++)
+               p++;
+       *p++ = '/';
+       q = unique;
+       while (*p = *q++)
+               p++;
+       i = fileargs;
+       do
+               *p++ = i % 10 + '0';
+       while (i /= 10);
+       *p++ = '.'; *p++ = suf; *p++ = '\0';
+       q = charp; charp = p;
+       return(q);
+}
+
+call(v,in,out) char **v,*in,*out; {
+       register pid;
+       int     status;
+
+       while ((parent = fork()) < 0)
+               sleep(1);
+       if (parent == 0) {
+               if (in) {
+                       close(0);
+                       if (open(in,0) != 0)
+                               syserr(in);
+               }
+               if (out) {
+                       close(1);
+                       if (creat(out,0666) != 1)
+                               syserr(out);
+               }
+               *v = 0;
+               execv(callvector[0],callvector+1);
+               syserr(callvector[0]);
+       }
+       while ((pid = wait(&status)) != parent) {
+               if (pid == -1)
+                       fatal("process %d disappeared",parent);
+               fatal("unknown child %d died",pid);
+       }
+       if ((status & 0177) > 3) {
+/*
+               if ((status & 0200) && tflag==0)
+                       unlink("core");
+*/
+               fatal("signal %d in %s. Ask an expert for help",
+                               status&0177,callvector[0]);
+       }
+       if (status & 0177400)
+               toterr++;
+}
+
+char **initvector(path) char *path; {
+       register char *p,**v;
+
+       v = callvector;
+       p = path;
+       *v++ = p;
+       *v++ = basename(p);
+       return(v);
+}
+
+finish() {
+       register char *p,*q;
+       register fd;
+       struct direct dir;
+
+       signal(SIGINT,SIG_IGN);
+       if (parent != 0) {
+               chdir(tmp_dir);
+               fd = open(".",0);
+               while (read(fd,(char *) &dir,sizeof dir) == sizeof dir) {
+                       if (dir.d_ino == 0)
+                               continue;
+                       p = unique;
+                       q = dir.d_name;
+                       while (*p++ == *q++)
+                               if (*p == '\0') {
+                                       unlink(dir.d_name);
+                                       break;
+                               }
+               }
+               close(fd);
+       }
+       exit(toterr ? -1 : 0);
+}
+
+
+donewith(p) char *p; {
+
+       if (p >= charbuf && p < &charbuf[CHARSIZE])
+               unlink(p);
+}
+
+init() {
+       register char *p;
+       register i,fd;
+
+       if ((fd = open(tmp_dir,0)) < 0)
+               tmp_dir = ".";
+       close(fd);
+       p = unique+2;
+       parent = i = getpid();
+       do
+               *p++ = i % 10 + '0';
+       while (i /= 10);
+       *p++ = '.'; *p = '\0';
+}
+
+/* ------------------- pascal listing ----------------------- */
+
+#define MAXERNO         300
+#define MAXERRLIST      10
+#define IDMAX           8
+
+struct errec {
+       int     erno;
+       char    mess[IDMAX+1];
+       int     mesi;
+       int     chno;
+       int     lino;
+};
+
+struct  errec   curr;
+struct  errec   next;
+
+int     *index          = 0;
+int     maxerno;
+
+int     errerr;
+int     errfat;
+
+int     listlino;
+int     listorig;
+int     listrela;
+char    *listfnam;
+
+FILE    *inpfil;
+FILE    *mesfil;
+FILE    *errfil;
+
+int     errorline();
+int     geterrec();
+int     nexterror();
+
+int list(p,q) char *p,*q; {
+
+       if ((errfil = fopen(q,"r")) == NULL)
+               syserr(q);
+       if (geterrec() == 0)
+               if (eeflag==0) {
+                       fclose(errfil);
+                       return(0);
+               }
+       if (index == 0) {
+               index = (int *) sbrk(MAXERNO * sizeof index[0]);
+               fillindex();
+       }
+       if ((inpfil = fopen(p,"r")) == NULL)
+               syserr(p);
+       errerr = 0;
+       errfat = 0;
+       listlino = 0;
+       listorig = 0;
+       listrela = 0;
+       listfnam = source;
+       if (eeflag)
+               listfull();
+       else if (eflag)
+               listpartial();
+       else
+               listshort();
+       fclose(errfil);
+       fclose(inpfil);
+       fflush(stdout);
+       return(errfat ? -1 : 1);
+}
+
+listshort() {
+
+       while (nexterror()) {
+               while (listlino < curr.lino)
+                       nextline(0);
+               printf("%s, %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 (file)
index 0000000..7a97bca
--- /dev/null
@@ -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 <stdio.h>
+
+/************************************************************************/
+/*                                                                      */
+/*           Read machine definitions and transformations               */
+/*                                                                      */
+/************************************************************************/
+
+#define COMMENT '#'
+
+#define VAR     "var"
+#define PASS    "name"
+#define IN      "from"
+#define OUT     "to"
+#define PROG    "program"
+#define MAPF    "mapflag"
+#define ARGS    "args"
+#define PROP    "prop"
+#define RUNT    "rts"
+#define NEEDT  "need"
+#define END     "end"
+
+extern growstring scanb();
+extern growstring scanvars();
+
+int getline() ;
+int getinchar() ;
+static char *ty_name ;
+static char *bol ;
+
+
+static char *inname ;
+
+setlist(name) char *name ; {
+       /* Name is sought in the internal tables,
+          if not present, the a file of that name is sought
+          in first the current and then the EM Lib directory
+       */
+
+       inname=name ;
+       open_in(name) ;
+       while ( getline() ) {
+               if ( strcmp(VAR,ty_name)==0 ) {
+                       doassign(bol,(char *)0,0) ;
+               } else
+               if ( strcmp(PASS,ty_name)==0 ) {
+                       intrf() ;
+               } else
+                       error("unknown keyword %s",ty_name) ;
+       }
+       close_in();
+#ifdef DEBUG
+       if ( debug>=3 ) vprint("End %s\n",name) ;
+#endif
+}
+
+intrf() {
+       register trf *new ;
+       register char *ptr ;
+       growstring bline, vline ;
+       int twice ;
+
+       new= (trf *)getcore(sizeof *new) ;
+       new->t_name= keeps(bol) ;
+       for (;;) {
+               if ( !getline() ) {
+                       fuerror("unexpected EOF on %s",inname) ;
+               }
+               twice= NO ;
+               if ( strcmp(ty_name,IN)==0 ) {
+                       if ( new->t_in ) twice=YES ;
+                       new->t_in= keeps(bol);
+               } else
+               if ( strcmp(ty_name,OUT)==0 ) {
+                       if ( new->t_out ) twice=YES ;
+                       new->t_out= keeps(bol);
+               } else
+               if ( strcmp(ty_name,PROG)==0 ) {
+                       if ( new->t_prog ) twice=YES ;
+                       bline= scanb(bol);                /* Scan for \ */
+                       vline= scanvars(gr_start(bline)); /* Scan for {} */
+                       gr_throw(&bline);
+                       new->t_prog= gr_final(&vline);
+                       clr_noscan(new->t_prog);
+               } else
+               if ( strcmp(ty_name,MAPF)==0 ) {
+                       /* First read the mapflags line
+                               and scan for backslashes */
+                       bline= scanb(bol) ;
+                       l_add(&new->t_mapf,gr_final(&bline)) ;
+               } else
+               if ( strcmp(ty_name,ARGS)==0 ) {
+                       if ( new->t_argd ) twice=YES ;
+                       bline= scanb(bol) ;
+                       new->t_argd= keeps(gr_start(bline)) ;
+                       gr_throw(&bline) ;
+               } else
+               if ( strcmp(ty_name,PROP)==0 ) {
+                       for ( ptr=bol ; *ptr ; ptr++ ) {
+                               switch( *ptr ) {
+                               case C_IN: new->t_stdin= YES ; break ;
+                               case C_OUT: new->t_stdout= YES ; break ;
+                               case 'P': new->t_isprep= YES ; break ;
+                               case 'p': new->t_prep= YES ; break ;
+                               case 'm': new->t_prep= MAYBE ; break ;
+                               case 'O': new->t_optim= YES ; break ;
+                               case 'C': new->t_combine= YES ; break ;
+                               default :
+                                 error("Unkown option %c in %s for %s",
+                                       *ptr,new->t_name,inname) ;
+                                 break ;
+                               }
+                       }
+               } else
+               if ( strcmp(ty_name,RUNT)==0 ) {
+                       if ( new->t_rts ) twice=YES ;
+                       new->t_rts= keeps(bol) ;
+               } else
+               if ( strcmp(ty_name,NEEDT)==0 ) {
+                       if ( new->t_needed ) twice=YES ;
+                       new->t_needed= keeps(bol) ;
+               } else
+               if ( strcmp(ty_name,END)==0 ) {
+                       break ;
+               } else {
+                       fuerror("illegal keyword %s %s",ty_name,bol);
+               }
+               if ( twice ) {
+                       werror("%s: specified twice for %s",
+                               ty_name, new->t_name) ;
+               }
+       }
+       if ( ! ( new->t_name && new->t_out && new->t_prog ) ) {
+               fuerror("insufficient specification for %s in %s",
+                       new->t_name,inname) ;
+       }
+       if ( ! new->t_argd ) new->t_argd="" ;
+#ifdef DEBUG
+       if ( debug>=3 ) {
+               register list_elem *elem ;
+               vprint("%s: from %s to %s '%s'\n",
+                       new->t_name,new->t_in,new->t_out,new->t_prog) ;
+               vprint("\targs: ") ; prns(new->t_argd) ;
+               scanlist( l_first(new->t_mapf), elem ) {
+                       vprint("\t%s\n",l_content(*elem)) ;
+               }
+               if ( new->t_rts ) vprint("\trts: %s\n",new->t_rts) ;
+               if ( new->t_needed ) vprint("\tneeded: %s\n",new->t_needed) ;
+       }
+#endif
+       l_add(&tr_list,(char *)new) ;
+}
+
+/************************** IO from core or file *******************/
+
+static  int             incore ;
+static  growstring      rline ;
+static  FILE            *infile ;
+static  char            *inptr ;
+
+open_in(name) register char *name ; {
+       register dmach *cmac ;
+
+       gr_init(&rline) ;
+       for ( cmac= massoc ; cmac->ma_index!= -1 ; cmac++ ) {
+               if ( strcmp(name,cmac->ma_name)==0 ) {
+                       incore=YES ;
+                       inptr= &intable[cmac->ma_index] ;
+                       return ;
+               }
+       }
+       /* Not in core */
+       incore= NO ;
+       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 (file)
index 0000000..a55c759
--- /dev/null
@@ -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 <signal.h>
+
+#define ARG_MORE  40            /* The size of args chunks to allocate */
+
+static char      **arglist ;    /* The first argument */
+static unsigned  argcount ;     /* The current number of arguments */
+static unsigned  argmax;        /* The maximum number of arguments so far */
+
+int do_run() {
+       fatal("-g flag not implemeted") ;
+       /*NOTREACHED*/
+       return 0 ;
+}
+
+int runphase(phase) register trf *phase ; {
+       register list_elem *elem ;
+
+       if ( v_flag || debug ) {
+               if ( v_flag==1 && !debug ) {
+                       vprint("%s",phase->t_name) ;
+                       if ( !phase->t_combine ) {
+                               vprint(" %s%s\n",p_basename,
+                                       rindex(in.p_path,SUFCHAR) ) ;
+                       } else {
+                               scanlist(l_first(c_arguments), elem) {
+                                       vprint(" %s",l_content(*elem)) ;
+                               }
+                               vprint("\n") ;
+                       }
+               } else {
+                       /* list all args */
+                       vprint("%s",phase->t_prog) ;
+                       scanlist(l_first(phase->t_flags), elem) {
+                               vprint(" %s",l_content(*elem)) ;
+                       }
+                       scanlist(l_first(phase->t_args), elem) {
+                               vprint(" %s",l_content(*elem)) ;
+                       }
+                       vprint("\n") ;
+               }
+       }
+       argcount=0 ;
+       x_arg(phase->t_name) ;
+       scanlist(l_first(phase->t_flags), elem) {
+               x_arg(l_content(*elem)) ;
+       }
+       scanlist(l_first(phase->t_args), elem) {
+               x_arg(l_content(*elem)) ;
+       }
+       x_arg( (char *)0 ) ;
+       return run_exec(phase) ;
+}
+
+int run_exec(phase) trf *phase ; {
+       int status, child, waitchild ;
+
+       do_flush();
+       while ( (child=fork())== -1 ) ;
+       if ( child ) {
+               /* The parent */
+               do {
+                       waitchild= wait(&status) ;
+                       if ( waitchild== -1 ) {
+                               fatal("missing child") ;
+                       }
+               } while ( waitchild!=child) ;
+               if ( status ) {
+                       if ( status&0200 && (status&0177)!=SIGQUIT &&
+                               !t_flag ) unlink("core") ;
+                       switch ( status&0177 ) {
+                       case 0 :
+                               break ;
+                       case SIGHUP:
+                       case SIGINT:
+                       case SIGQUIT:
+                       case SIGTERM:
+                               quit(-5) ;
+                       default:
+                               error("%s died with signal %d",
+                                       phase->t_prog,status&0177) ;
+                       }
+                       /* The assumption is that processes voluntarely
+                          dying with a non-zero status already produced
+                          some sort of error message to the outside world.
+                       */
+                       n_error++ ;
+                       return 0 ;
+               }
+               return 1 ; /* From the parent */
+       }
+       /* The child */
+       if ( phase->t_stdin ) {
+               if ( !in.p_path ) {
+                       fatal("no input file for %s",phase->t_name) ;
+               }
+               close(0) ;
+               if ( open(in.p_path,0)!=0 ) {
+                       error("cannot open %s",in.p_path) ;
+                       exit(1) ;
+               }
+       }
+       if ( phase->t_stdout ) {
+               if ( !out.p_path ) {
+                       fatal("no output file for %s",phase->t_name) ;
+               }
+               close(1) ;
+               if ( creat(out.p_path,0666)!=1 ) {
+                       close(1); dup(2);
+                       error("cannot open %s",out.p_path) ;
+                       exit(1) ;
+               }
+       }
+       execv(phase->t_prog,arglist) ;
+       if ( phase->t_stdout ) { close(1) ; dup(2) ; }
+       error("Cannot execute %s",phase->t_prog) ;
+       exit(1) ;
+       /*NOTREACHED*/
+}
+
+x_arg(string) char *string ; {
+       /* Add one execute argument to the argument vector */
+       if ( argcount==argmax ) {
+               if ( argmax==0 ) {
+                       argmax= 2*ARG_MORE ;
+                       arglist= (char **)getcore(argmax*sizeof (char *)) ;
+               } else {
+                       argmax += ARG_MORE ;
+                       arglist= (char **)changecore((char *)arglist,
+                                       argmax*sizeof (char *)) ;
+               }
+       }
+       *(arglist+argcount++) = string ;
+}
diff --git a/util/ack/scan.c b/util/ack/scan.c
new file mode 100644 (file)
index 0000000..63a5b7c
--- /dev/null
@@ -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_ocount<ocount : last_ocount>ocount ) ) ) {
+               /* Yes it is */
+#ifdef DEBUG
+               if ( debug>=3 ) vprint("Better\n");
+#endif
+               scanlist(l_first(tr_list),scan) {
+                       t_cont(*scan)->t_do=t_cont(*scan)->t_scan;
+               }
+               last_ncount=ncount; last_ocount=ocount;
+               if ( keepit ) final=keepit ;
+       }
+}
+
+int satisfy(trafo,suffix) register trf *trafo; char *suffix ; {
+       register char *f_char, *l_char ;
+       /* Check whether this transformation is present for
+          the current machine and the parameter suffix is among
+          the input suffices. If so, return 1. 0 otherwise
+       */
+       if ( trafo->t_isprep ) return 0 ;
+       l_char=trafo->t_in ;
+       while ( l_char ) {
+               f_char= l_char ;
+               if ( *f_char!=SUFCHAR || ! *(f_char+1) ) {
+                       fuerror("Illegal input suffix entry for %s",
+                               trafo->t_name) ;
+               }
+               l_char=index(f_char+1,SUFCHAR);
+               if ( l_char ? strncmp(f_char,suffix,l_char-f_char)==0 :
+                             strcmp(f_char,suffix)==0 ) {
+                       return 1 ;
+               }
+       }
+       return 0 ;
+}
+
+enum f_path scan_end() {    /* Finalization */
+       /* Return value indicating whether a transformation was found */
+       /* Set the flags for the transformation up to, but not including,
+          the combiner
+       */
+
+#ifdef DEBUG
+       if ( debug>=3 ) vprint("End_scan\n");
+#endif
+       if ( last_ncount== -1 ) return suf_found ? F_NOPATH : F_NOMATCH ;
+#ifdef DEBUG
+       if ( debug>=2 ) vprint("Transformation found\n");
+#endif
+       if ( cpp_trafo && stopsuffix &&
+            strcmp(stopsuffix,cpp_trafo->t_out)==0 ) {
+               final= cpp_trafo ;
+       }
+       /* There might not be a final when the file can be eaten
+          by the combiner
+       */
+       if ( final ) final->t_keep=YES ;
+       if ( combiner ) {
+               if ( !combiner->t_do ) error("Combiner YES/NO");
+               combiner->t_do=NO ;
+       }
+       return F_OK ;
+}
+
+find_cpp() {
+       register list_elem *elem ;
+       scanlist( l_first(tr_list), elem ) {
+               if ( t_cont(*elem)->t_isprep ) {
+                       if ( cpp_trafo ) fuerror("Multiple cpp's present") ;
+                       cpp_trafo= t_cont(*elem) ;
+               }
+       }
+       if ( !cpp_trafo ) fuerror("No cpp present") ;
+}
diff --git a/util/ack/svars.c b/util/ack/svars.c
new file mode 100644 (file)
index 0000000..4749fe1
--- /dev/null
@@ -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 (file)
index 0000000..3eeab98
--- /dev/null
@@ -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 && eq<eos ) eos= eq ;
+       }
+       if ( !eos ) fuerror("Incorrect use of -R flag") ;
+       length= eos - &argp[2] ;
+       seen=NO ;
+       scanlist(l_first(tr_list), prog) {
+               if ( strncmp(t_cont(*prog)->t_name, &argp[2], length )==0 ) {
+                       if ( *eos=='-' ) {
+                               l_add(&(t_cont(*prog)->t_flags),eos) ;
+                       } else {
+                               t_cont(*prog)->t_prog= eos+1 ;
+                       }
+                       seen=YES ;
+               }
+       }
+       if ( !seen ) error("Cannot find program for %s",argp) ;
+       return ;
+}
+
+/**************************************************************************/
+/*                                                                        */
+/*           The creation of arguments for exec for a transformation      */
+/*                                                                        */
+/**************************************************************************/
+
+growstring scanb(line) char *line ; {
+       /* Scan a line for backslashes, setting the NO_SCAN bit in characters
+          preceded by a backslash.
+       */
+       register char *in_c ;
+       register int  token ;
+       growstring result ;
+       enum { TEXT, ESCAPED } state = TEXT ;
+
+       gr_init(&result) ;
+       for ( in_c= line ; *in_c ; in_c++ ) {
+               token= *in_c&0377 ;
+               switch( state ) {
+               case TEXT :
+                       if ( token==BSLASH ) {
+                               state= ESCAPED ;
+                       } else {
+                               gr_add(&result,token) ;
+                       }
+                       break ;
+               case ESCAPED :
+                       gr_add(&result,token|NO_SCAN) ;
+                       state=TEXT ;
+                       break ;
+               }
+       }
+       gr_add(&result,0) ;
+       if ( state!=TEXT ) werror("flag line ends with %c",BSLASH) ;
+       return result ;
+}
+
+growstring scanvars(line) char *line ; {
+       /* Scan a line variable replacements started by S_VAR.
+          Two sequences exist: S_VAR name E_VAR, S_VAR name A_VAR text E_VAR.
+          neither name nor text may contain further replacements.
+          In the first form an error message is issued if the name is not
+          present in the variables, the second form produces text
+          in that case.
+          The sequence S_VAR S_VAR is transformed into S_VAR.
+          This to allow later recognition in mapflags, where B_SLASH
+          would be preventing any recognition.
+       */
+       register char *in_c ;
+       register int  token ;
+       growstring result ;
+       growstring name ;
+       register char *tr ;
+       enum { TEXT, FIRST, NAME, SKIP, COPY } state = TEXT ;
+
+       gr_init(&result) ; gr_init(&name) ;
+       for ( in_c= line ; *in_c ; in_c++ ) {
+               token= *in_c&0377 ;
+               switch( state ) {
+               case TEXT :
+                       if ( token==S_VAR ) {
+                               state= FIRST ;
+                       } else {
+                               gr_add(&result,token) ;
+                       }
+                       break ;
+               case FIRST :
+                       switch ( token ) {
+                       case S_VAR :
+                               state= TEXT ;
+                               gr_add(&result,token) ;
+                               break ;
+                       case A_VAR :
+                       case C_VAR :
+                               fatal("empty string variable name") ;
+                       default :
+                               state=NAME ;
+                               gr_add(&name,token) ;
+                               break ;
+                       }
+                       break ;
+               case NAME:
+                       switch ( token ) {
+                       case A_VAR :
+                               gr_add(&name,0) ;
+                               if ( tr=getvar(gr_start(name)) ) {
+                                       while ( *tr ) {
+                                               gr_add(&result,*tr++) ;
+                                       }
+                                       state=SKIP ;
+                               } else {
+                                       state=COPY ;
+                               }
+                               gr_throw(&name) ;
+                               break ;
+                       case C_VAR :
+                               gr_add(&name,0) ;
+                               if ( tr=getvar(gr_start(name)) ) {
+                                       while ( *tr ) {
+                                          gr_add(&result,*tr++);
+                                       }
+                               } else {
+                                       werror("No definition for %s",
+                                               gr_start(name)) ;
+                               }
+                               state=TEXT ;
+                               gr_throw(&name) ;
+                               break ;
+                       default:
+                               gr_add(&name,token) ;
+                               break ;
+                       }
+                       break ;
+               case SKIP :
+                       if ( token==C_VAR ) state= TEXT ;
+                       break ;
+               case COPY :
+                       if ( token==C_VAR ) state= TEXT ; else {
+                               gr_add(&result,token) ;
+                       }
+                       break ;
+               }
+       }
+       gr_add(&result,0) ;
+       if ( state!=TEXT ) {
+               werror("flag line misses %c",C_VAR) ;
+               gr_throw(&name) ;
+       }
+       return result ;
+}
+
+growstring scanexpr(line) char *line ; {
+       /* Scan a line for conditional or flag expressions,
+          dependent on the type. The format is
+          S_EXPR suflist M_EXPR suflist T_EXPR tail C_EXPR
+          the head and tail are passed to treat, together with the
+          growstring for futher treatment.
+          Nesting is not allowed.
+       */
+       register char *in_c ;
+       char *heads ;
+       register int  token ;
+       growstring sufs, tailval ;
+       growstring result ;
+       static list_head fsuff, lsuff ;
+       enum { TEXT, FDOT, FSUF, LDOT, LSUF, FTAIL } state = TEXT ;
+
+       gr_init(&result) ; gr_init(&sufs) ; gr_init(&tailval) ;
+       for ( in_c= line ; *in_c ; in_c++ ) {
+               token= *in_c&0377 ;
+               switch( state ) {
+               case TEXT :
+                       if ( token==S_EXPR ) {
+                               state= FDOT ;
+                               heads=in_c ;
+                       } else gr_add(&result,token) ;
+                       break ;
+               case FDOT :
+                       if ( token==M_EXPR ) {
+                               state=LDOT ;
+                               break ;
+                       }
+                       token &= ~NO_SCAN ;
+                       if ( token!=SUFCHAR ) {
+                               error("Missing %c in expression",SUFCHAR) ;
+                       }
+                       gr_add(&sufs,token) ; state=FSUF ;
+                       break ;
+               case FSUF :
+                       if ( token==M_EXPR || (token&~NO_SCAN)==SUFCHAR) {
+                               gr_add(&sufs,0) ;
+                               l_add(&fsuff,gr_final(&sufs)) ;
+                       }
+                       if ( token==M_EXPR ) {
+                               state=LDOT ;
+                       } else gr_add(&sufs,token&~NO_SCAN) ;
+                       break ;
+               case LDOT :
+                       if ( token==T_EXPR ) {
+                               state=FTAIL ;
+                               break ;
+                       }
+                       token &= ~NO_SCAN ;
+                       if ( token!=SUFCHAR ) {
+                               error("Missing %c in expression",SUFCHAR) ;
+                       }
+                       gr_add(&sufs,token) ; state=LSUF ;
+                       break ;
+               case LSUF :
+                       if ( token==T_EXPR || (token&~NO_SCAN)==SUFCHAR) {
+                               gr_add(&sufs,0) ;
+                               l_add(&lsuff,gr_final(&sufs)) ;
+                       }
+                       if ( token==T_EXPR ) {
+                               state=FTAIL ;
+                       } else gr_add(&sufs,token&~NO_SCAN) ;
+                       break ;
+               case FTAIL :
+                       if ( token==C_EXPR ) {
+                               /* Found one !! */
+                               gr_add(&tailval,0) ;
+                               condit(&result,&fsuff,&lsuff,gr_start(tailval)) ;
+                               l_throw(&fsuff) ; l_throw(&lsuff) ;
+                               gr_throw(&tailval) ;
+                               state=TEXT ;
+                       } else gr_add(&tailval,token) ;
+                       break ;
+               }
+       }
+       gr_add(&result,0) ;
+       if ( state!=TEXT ) {
+               l_throw(&fsuff) ; l_throw(&lsuff) ; gr_throw(&tailval) ;
+               werror("flag line has unclosed expression starting with %6s",
+                       heads) ;
+       }
+       return result ;
+}
+
+condit(line,fsuff,lsuff,tailval) growstring *line ;
+       list_head *fsuff, *lsuff;
+       char *tailval ;
+{
+       register list_elem *first ;
+       register list_elem *last ;
+
+#ifdef DEBUG
+       if ( debug>=4 ) vprint("Conditional for %s, ",tailval) ;
+#endif
+       scanlist( l_first(*fsuff), first ) {
+               scanlist( l_first(*lsuff), last ) {
+                       if ( strcmp(l_content(*first),l_content(*last))==0 ) {
+                               /* Found */
+#ifdef DEBUG
+                               if ( debug>=4 ) vprint(" matched\n") ;
+#endif
+                               while ( *tailval) gr_add(line,*tailval++ ) ;
+                               return ;
+                       }
+               }
+       }
+#ifdef DEBUG
+       if ( debug>=4) vprint(" non-matched\n") ;
+#endif
+}
+
+int mapflag(maplist,cflag) list_head *maplist ; char *cflag ; {
+       /* Expand a flag expression */
+       /* The flag "cflag" is checked for each of the mapflags.
+          A mapflag entry has the form
+               -text NAME=replacement or -text*text NAME=replacement
+          The star matches anything as in the shell.
+          If the entry matches the assignment will take place
+          This replacement is subjected to argument matching only.
+          When a match took place the replacement is returned
+          when not, (char *)0.
+          The replacement sits in stable storage.
+       */
+       register list_elem *elem ;
+
+       scanlist(l_first(*maplist),elem) {
+               if ( mapexpand(l_content(*elem),cflag) ) {
+                       return 1 ;
+               }
+       }
+       return 0 ;
+}
+
+int mapexpand(mapentry,cflag)
+       char *mapentry, *cflag ;
+{
+       register char *star ;
+       register char *ptr ;
+       register char *space ;
+       int length ;
+
+       star=index(mapentry,STAR) ;
+       space=firstblank(mapentry) ;
+       if ( star >space ) star= (char *)0 ;
+       if ( star ) {
+               length= space-star-1 ;
+               if ( strncmp(mapentry,cflag,star-mapentry) ||
+                    strncmp(star+1,cflag+strlen(cflag)-length,length) ) {
+                       return 0 ;
+               }
+               /* Match */
+               /* Now set star to the first char of the star
+                  replacement and length to its length
+               */
+               length=strlen(cflag)-(star-mapentry)-length ;
+               if ( length<0 ) return 0 ;
+               star=cflag+(star-mapentry) ;
+#ifdef DEBUG
+               if ( debug>=6 ) {
+                       vprint("Starmatch (%s,%s) %.*s\n",
+                               mapentry,cflag,length,star) ;
+               }
+#endif
+       } else {
+               if ( strncmp(mapentry,cflag,space-mapentry)!=0 ||
+                    cflag[space-mapentry] ) {
+                       return 0 ;
+               }
+       }
+       ptr= skipblank(space) ;
+       if ( *ptr==0 ) return 1 ;
+       doassign(ptr,star,length) ;
+       return 1 ;
+}
+
+doassign(line,star,length) char *line, *star ; {
+       growstring varval, name, temp ;
+       register char *ptr ;
+
+       gr_init(&varval) ;
+       gr_init(&name) ;
+       ptr= line ;
+       for ( ; *ptr && *ptr!=SPACE && *ptr!=TAB && *ptr!=EQUAL ; ptr++ ) {
+               gr_add(&name,*ptr) ;
+       }
+       ptr= index(ptr,EQUAL) ;
+       if ( !ptr ) {
+               error("Missing %c in assignment %s",EQUAL,line);
+               return ;
+       }
+       temp= scanvars(ptr+1) ;
+       for ( ptr=gr_start(temp); *ptr; ptr++ ) switch ( *ptr ) {
+       case STAR :
+               if ( star ) {
+                       while ( length-- ) gr_add(&varval,*star++|NO_SCAN) ;
+                       break ;
+               }
+       default :
+               gr_add(&varval,*ptr) ;
+               break ;
+       }
+       gr_throw(&temp) ;
+       setsvar(gr_final(&name),gr_final(&varval)) ;
+}
+
+#define ISBLANK(c) ( (c)==SPACE || (c)==TAB )
+
+unravel(line,action) char *line ; int (*action)() ; {
+       /* Unravel the line, get arguments a la shell */
+       /* each argument is handled to action */
+       /* The input string is left intact */
+       register char *in_c ;
+       register int  token ;
+       enum { BLANK, ARG } state = BLANK ;
+       growstring argum ;
+
+       in_c=line ;
+       for (;;) {
+               token= *in_c&0377 ;
+               switch ( state ) {
+               case BLANK :
+                       if ( token==0 ) break ;
+                       if ( !ISBLANK(token) ) {
+                               state= ARG ;
+                               gr_init(&argum) ;
+                               gr_add(&argum,token&~NO_SCAN) ;
+                       }
+                       break ;
+               case ARG :
+                       if ( ISBLANK(token) || token==0 ) {
+                               gr_add(&argum,0) ;
+                               (*action)(gr_start(argum)) ;
+                               gr_throw(&argum) ;
+                               state=BLANK ;
+                       } else {
+                               gr_add(&argum,token&~NO_SCAN) ;
+                       }
+                       break ;
+               }
+               if ( token == 0 ) break ;
+               in_c++ ;
+       }
+}
+
+char *c_rep(string,place,rep) char *string, *place, *rep ; {
+       /* Produce a string in stable storage produced from 'string'
+          with the character at place replaced by rep
+       */
+       growstring name ;
+       register char *nc ;
+       register char *xc ;
+
+       gr_init(&name) ;
+       for ( nc=string ; *nc && nc<place ; nc++ ) {
+               gr_add(&name,*nc) ;
+       }
+#ifdef DEBUG
+       if ( *nc==0 ) fatal("Place is not in string") ;
+#endif
+       for ( xc=rep ; *xc ; xc++ ) gr_add(&name,*xc|NO_SCAN) ;
+       gr_add(&name,0) ;
+       gr_cat(&name,nc+1) ;
+       return gr_final(&name) ;
+}
+
+static list_head *curargs ;
+
+addargs(string) char *string ; {
+       register char *temp, *repc ;
+       register list_elem *elem ;
+
+       repc=index(string,C_IN) ;
+       if ( repc ) {
+               /* INPUT FILE TOKEN seen, replace it and scan further */
+               if ( repc==string && string[1]==0 ) {
+                       if ( in.p_path ) { /* All but combiner */
+                               l_add(curargs,keeps(in.p_path)) ;
+                       } else {
+                               scanlist( l_first(c_arguments), elem ) {
+                                       l_add(curargs,l_content(*elem)) ;
+                               }
+                       }
+                       return ;
+               }
+               if ( in.p_path ) { /* Not for the combiner */
+                       temp=c_rep(string,repc,in.p_path) ;
+                       addargs(temp) ;
+                       throws(temp) ;
+               } else {           /* For the combiner */
+                       scanlist( l_first(c_arguments), elem ) {
+                               temp=c_rep(string,repc,l_content(*elem)) ;
+                               addargs(temp) ;
+                               throws(temp) ;
+                       }
+               }
+               return ;
+       }
+       repc=index(string,C_OUT) ;
+       if ( repc ) {
+               /* replace the outfile token as with the infile token */
+#ifdef DEBUG
+               if ( !out.p_path ) fatal("missing output filename") ;
+#endif
+               temp=c_rep(string,repc,out.p_path) ;
+               addargs(temp) ;
+               throws(temp) ;
+               return ;
+       }
+       temp= keeps(string) ;
+       clr_noscan(temp) ;
+       l_add(curargs,temp) ;
+}
+
+getcallargs(phase) register trf *phase ; {
+       growstring arg1, arg2 ;
+
+       arg1= scanvars(phase->t_argd) ;
+#ifdef DEBUG
+       if ( debug>=3 ) { vprint("\tvars: ") ; prns(gr_start(arg1)) ; }
+#endif
+       arg2= scanexpr(gr_start(arg1)) ;
+#ifdef DEBUG
+       if ( debug>=3 ) { vprint("\texpr: ") ; prns(gr_start(arg2)) ; }
+#endif
+       gr_throw(&arg1) ;
+       curargs= &phase->t_args ;
+       unravel( gr_start(arg2), addargs ) ;
+       gr_throw(&arg2) ;
+}
+
+discardargs(phase) register trf *phase ; {
+       l_throw(&phase->t_args) ;
+}
diff --git a/util/ack/trans.h b/util/ack/trans.h
new file mode 100644 (file)
index 0000000..7e305d6
--- /dev/null
@@ -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 (file)
index 0000000..ac32f38
--- /dev/null
@@ -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 <ctype.h>
+#include <stdio.h>
+
+extern  char    *progname ;
+extern  int     w_flag ;
+extern  int     n_error;
+
+extern  char    *calloc();
+extern  char    *realloc();
+
+#ifdef DEBUG
+# define STDOUT stdout
+#else
+# define STDOUT stderr
+#endif
+
+char *basename(string) char *string ; {
+       static char retval[20] ;
+       char *last_dot, *last_start ;
+       register char *store;
+       register char *fetch ;
+       register int ctoken ;
+
+       last_dot= (char *)0 ;
+       last_start= string ;
+       for ( fetch=string ; ; fetch++ ) {
+               switch ( ctoken= *fetch&0377 ) {
+               case SUFCHAR : last_dot=fetch ; break ;
+               case '/'     : last_start=fetch+1 ; break ;
+               case  0      : goto out ;
+               }
+               if ( !isascii(ctoken) || !isprint(ctoken) ) {
+                       werror("non-ascii characters in argument %s",string) ;
+               }
+       }
+out:
+       if ( ! *last_start ) fuerror("empty filename \"%s\"",string) ;
+       for ( fetch= last_start, store=retval ;
+               *fetch && fetch!=last_dot && store< &retval[sizeof retval-1] ;
+                     fetch++, store++ ) {
+                               *store= *fetch ;
+       }
+       *store= 0 ;
+       return retval ;
+}
+
+clr_noscan(str) char *str ; {
+       register char *ptr ;
+       for ( ptr=str ; *ptr ; ptr++ ) {
+               *ptr&= ~NO_SCAN ;
+       }
+}
+
+char *skipblank(str) char *str ; {
+       register char *ptr ;
+
+       for ( ptr=str ; *ptr==SPACE || *ptr==TAB ; ptr++ ) ;
+       return ptr ;
+}
+
+char *firstblank(str) char *str ; {
+       register char *ptr ;
+
+       for ( ptr=str ; *ptr && *ptr!=SPACE && *ptr!=TAB ; ptr++ ) ;
+       return ptr ;
+}
+
+/* VARARGS1 */
+fatal(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
+       /* Fatal internal error */
+       fprintf(STDOUT,"%s: fatal internal error, ",progname) ;
+       fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
+       fprintf(STDOUT,"\n") ;
+       quit(-2) ;
+}
+
+
+/* VARARGS1 */
+vprint(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
+       /* Diagnostic print, no auto NL */
+       fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
+}
+
+#ifdef DEBUG
+prns(s) register char *s ; {
+       for ( ; *s ; s++ ) {
+               putc((*s&0377)&~NO_SCAN,STDOUT) ;
+       }
+       putc('\n',STDOUT) ;
+}
+#endif
+
+/* VARARGS1 */
+fuerror(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
+       /* Fatal user error */
+       fprintf(STDOUT,"%s: ",progname) ;
+       fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
+       fprintf(STDOUT,"\n") ;
+       quit(-1) ;
+}
+
+/* VARARGS1 */
+werror(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
+       /* Warning user error, w_flag */
+       if ( w_flag ) return ;
+       fprintf(STDOUT,"%s: warning, ",progname) ;
+       fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
+       fprintf(STDOUT,"\n") ;
+}
+
+/* VARARGS1 */
+error(fmt,p1,p2,p3,p4,p5,p6,p7) char *fmt ; {
+       /* User error, it is the callers responsibility to quit */
+       fprintf(STDOUT,"%s: ",progname) ;
+       fprintf(STDOUT,fmt,p1,p2,p3,p4,p5,p6,p7);
+       fprintf(STDOUT,"\n") ;
+       n_error++ ;
+}
+
+do_flush() {
+       fflush(stdout) ;
+       fflush(stderr) ;
+}
+
+noodstop() {
+       quit(-3) ;
+}
+
+quit(code) {
+       rmtemps();
+       exit(code);
+}
+/******
+       char *keeps(string)
+               Keep the string in stable storage.
+       throws(string)
+               Remove the string stored by keep from stable storage.
+***********/
+
+char *keeps(str) char *str ; {
+       register char *result ;
+       result= getcore( (unsigned)(strlen(str)+1) ) ;
+       if ( !result ) fatal("Out of core") ;
+       return strcpy(result,str) ;
+}
+
+throws(str) char *str ; {
+       freecore(str) ;
+}
+
+char *getcore(size) unsigned size ; {
+       register char *retptr ;
+
+       retptr= calloc(1,size) ;
+       if ( !retptr ) fatal("Out of memory") ;
+       return retptr ;
+}
+
+char *changecore(ptr,size) char *ptr ; unsigned size ; {
+       register char *retptr ;
+
+       retptr= realloc(ptr,size) ;
+       if ( !retptr ) fatal("Out of memory") ;
+       return retptr ;
+}