--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+# (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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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)
--- /dev/null
+/****************************************************************************/
+/* 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
--- /dev/null
+#include "ack.h"
+#include "list.h"
+#include "trans.h"
+
+
+#undef EXTERN
+#define EXTERN
+
+#include "data.h"
--- /dev/null
+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 */
--- /dev/null
+/***************************************************************/
+/* */
+/* 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[] ;
--- /dev/null
+/*
+ * (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 ;
+ }
+}
--- /dev/null
+/*
+ * (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 ;
+}
--- /dev/null
+/* 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 */
--- /dev/null
+/*
+ * (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 ;
+}
--- /dev/null
+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) )
--- /dev/null
+/*
+ * (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 ;
+ }
+}
--- /dev/null
+/*
+ * (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
--- /dev/null
+/*
+ * (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) ;
+}
--- /dev/null
+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
--- /dev/null
+/*
+ * (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();
+}
--- /dev/null
+/*
+ * (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 ;
+}
--- /dev/null
+/*
+ * (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 ;
+}
--- /dev/null
+/*
+ * (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") ;
+}
--- /dev/null
+/*
+ * (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 ;
+}
--- /dev/null
+/*
+ * (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) ;
+}
--- /dev/null
+/* 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))
--- /dev/null
+/*
+ * (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 ;
+}