Initial revision

This commit is contained in:
keie 1984-06-21 10:57:59 +00:00
parent 35f8666be0
commit 3b4b7cac60
35 changed files with 4011 additions and 0 deletions

27
lib/6500/descr Normal file
View file

@ -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

31
lib/6809/descr Normal file
View file

@ -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

25
lib/descr/cpm Normal file
View file

@ -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

60
lib/descr/fe.src Normal file
View file

@ -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

28
lib/descr/nascom Normal file
View file

@ -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

27
lib/em22/descr Normal file
View file

@ -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

27
lib/i80/descr Normal file
View file

@ -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

32
lib/i86/descr Normal file
View file

@ -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

30
lib/m68k2/descr Normal file
View file

@ -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

34
lib/m68k4/descr Normal file
View file

@ -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

38
lib/pdp/descr Normal file
View file

@ -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

37
lib/vax4/descr.src Normal file
View file

@ -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

31
lib/z80/descr Normal file
View file

@ -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

63
util/ack/Makefile Normal file
View file

@ -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)

88
util/ack/ack.h Normal file
View file

@ -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

9
util/ack/data.c Normal file
View file

@ -0,0 +1,9 @@
#include "ack.h"
#include "list.h"
#include "trans.h"
#undef EXTERN
#define EXTERN
#include "data.h"

43
util/ack/data.h Normal file
View file

@ -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 */

15
util/ack/dmach.h Normal file
View file

@ -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[] ;

94
util/ack/files.c Normal file
View file

@ -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 ;
}
}

79
util/ack/grows.c Normal file
View file

@ -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 ;
}

19
util/ack/grows.h Normal file
View file

@ -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 */

73
util/ack/list.c Normal file
View file

@ -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 ;
}

23
util/ack/list.h Normal file
View file

@ -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) )

340
util/ack/main.c Normal file
View file

@ -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 ;
}
}

208
util/ack/malloc.c Normal file
View file

@ -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

121
util/ack/mktables.c Normal file
View file

@ -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) ;
}

25
util/ack/pc/Makefile Normal file
View file

@ -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

681
util/ack/pc/em_pc.c Normal file
View file

@ -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();
}

288
util/ack/rmach.c Normal file
View file

@ -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 ;
}

154
util/ack/run.c Normal file
View file

@ -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 ;
}

244
util/ack/scan.c Normal file
View file

@ -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") ;
}

125
util/ack/svars.c Normal file
View file

@ -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 ;
}

672
util/ack/trans.c Normal file
View file

@ -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) ;
}

30
util/ack/trans.h Normal file
View file

@ -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))

190
util/ack/util.c Normal file
View file

@ -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 ;
}