Yet Another Shared CC

John R. MacMillan jrmacmillan at lily.waterloo.edu
Fri Oct 21 01:17:06 AEST 1988


Yes it is another one; none of the others worked just the way I wanted.
This is what I think /bin/cc _should_ have been.

See the ReadMe to see why you should use it.

--------------- Bend, fold, spindle, and mutilate here ---------------
#!/bin/sh
#  This is a shar file.  To extract, sh this file
#
#  Contents:
#	ReadMe
#	HelpMe
#	Makefile
#	shcc.man
#	munge.c
#	shcc.c
#	options.c
#	passes.c
#	load.c
#	shcc.h
#
#  Wrapped by john at mystic ; Thu Oct 20 10:41:00 EST 1988
#
if [ -f "ReadMe" ] ; then
	echo "shar: Will not overwrite existing file ReadMe"
else
	echo "shar: extracting ReadMe (3383 characters)"
	sed 's/^X//' <<'BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM' > ReadMe
XJust when you thought it was safe to compile...
X
XShcc - Yet Another Shared CC Driver
X
XWhat it does
X------------
X
XBy default, shcc will compile (hopefully) anything into an executable
Xthat uses the shared library.  It also can behave just like /bin/cc,
X(but you can't throw /bin/cc away just yet; shcc exec()s it for ONE
Xoption.  See the HelpMe for details), and has options for quicker
Xcompiling with shared libraries.
X
XWhy use it
X----------
X
XFor the same reasons I wrote it:
X
X1) It works.
X2) It's fast.
X
XAs far as working goes, it works for all the nasty cases, not just
Xsome of them.  None of ccc, ccs, or scc do to my satisfaction.  You
Xeither have to tell them about exceptions or they give you ugly
Xwarnings and you're never quite sure if it worked correctly or not.
X
XIt does this in much the same way as Gene H. Olson's scc does.
X(Aside: although I'd started playing with shcc before I saw scc, I was
Xamazed when I saw how Gene managed it with existing tools.  It hadn't
Xeven occurred to me that it was possible.)  That is, it does two load
Xpasses.  The first creates a relocatable object, which is scanned for
Xunresolved symbols, and a custom shlib.ifile is created.  The second
Xload pass creates the executable with the custom shlib.ifile.
X
XAnd it really does work.  I've compiled lots of little things, and
Xsome biggies including elm, mush, jove, and mh.
X
XAs for speed, well, it's not a shell script.  If you set CC=foo in a
Xtypical makefile, you get a bunch of "foo -c file.c" compiles and
Xfinally a "foo file.o ...".
X
XOn the first type, the scripts really lose.  And they're not really
Xnecessary.  Shcc on the other hand, holds its own with /bin/cc.  It's
Xa little bigger (because /lib/shlib.ifile is essentially compiled in),
Xso it's slightly slower loading the first time, but after that, real
Xand system times are almost the same, and user time is consistently
Xlower for shcc.
X
XOn the second type, /bin/cc isn't in it because it won't do shared
Xlibraries.  For small programs, the 2nd load pass of shcc doesn't slow
Xit down too much and it beats the scripts.  For large programs it's a
Xbit slower (except than scc, which also does a second pass) _unless_
Xyou used the option to save the custom ifile last time you compiled
Xit, in which case shcc wins again.  Besides, you saved all that time
Xon the -c compiles...
X
XOther Stuff
X-----------
X
XSee the Makefile to see how to build and install shcc.
X
XSee HelpMe so that you can...you guessed it...help me improve shcc.
X
XAcknowledgements go to the other writers of shared cc scripts,
Xespecially Jeffery Small, from who I ripped off how to build the mini
Xlibc, and to Bob Gibson, who was my beta test site, provided lots of
Xuseful suggestions, and also saved my life (well, shcc, anyway).
X
XDisclaimer
X----------
X
XI'm not responsible for any havoc this program may wreak.  So if it
Xremoves your source files, crashes your machine, refuses to do any-
Xthing you think it should, calls you names and questions your lineage,
Xor kidnaps your spouse and children, and burns down your house, don't
Xtry to sue me.  I don't have anything you'd want anyway.
X
XI would like to hear about any of the above, though; especially the
Xkidnapping your spouse and children one.
X
XSuggestions to:
X
Xjohn%mystic at math.waterloo.edu
X...!watmath!mystic!john
X
Xuntil 1989, at which point I'll be elsewhere.
X{utcsri,utzoo}!hcr!chance!john
Xif I had to guess.
BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM
	set -- `wc -c ReadMe`
	if [ "$1" != "3383" ] ; then
		echo "shar: ReadMe unpacked with wrong size!"
	fi
fi
if [ -f "HelpMe" ] ; then
	echo "shar: Will not overwrite existing file HelpMe"
else
	echo "shar: extracting HelpMe (2260 characters)"
	sed 's/^X//' <<'BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM' > HelpMe
XHelp me improve this program!
X
X1.	The obvious one: If you find any bugs, TELL ME.
X
X2.	I don't have a 3.5 or lower machine to try this on so let
X	me know about any changes you have to (or refuse to) make.
X
X3.	If you can tell me what the -X flag to /bin/cc does, please
X	do.
X
X4.	If you think I've gotten any of the behaviour "wrong", tell
X	me.  I've tried to be faithful, with a few known differences:
X
X	- Order of arguments to passes isn't always the same
X	- Some error messages are slightly different
X	- My -W doesn't limit the number of args, theirs does (I think
X          of this a "feature")
X	- The pass names in shcc aren't dependent on the program name
X          (try "ln /bin/cc mumblecc ; ./mumblecc -# foo.c" to see what
X          I mean)
X	- The -C option no longer takes an argument.  It's not supposed
X	  to, and I couldn't bear to leave it that way, so I fixed it.
X        - Exit values on signals aren't the same (if someone knows how
X	  /bin/cc is doing it, let me know)
X	- One or two other things that I've probably forgotton, but it
X          wouldn't hurt to tell me.
X
X	It's possible that some of the undocumented flags (eg. -K) are
X	not handled correctly, but I think they are.  Let me know if
X	you find a difference.
X
X5.	If any of the flags I (-j, -q, -h) added have another use else-
X	where that you think might conflict, let me know.
X
X6.	munge.c probably shouldn't be a C program; I should probably
X	use existing tools.  Make me an awk script I can't refuse...
X
X7.	I really wish I knew how to load -F.  If you do, please
X	enlighten me BUT the trick of putting /lib/crt0s.o in some
X	other place DOESN'T WORK, so don't tell me that.  (It just
X	fools the file(1) command).  Or show me that it works, and
X	I'll show you that it doesn't.
X
X8.	Do you think rather than compiling in /lib/shlib.ifile, it
X	should do it "on the fly"?  This would shrink the executable,
X	but slow it down when it had to do two passes.  The timings
X	I've done don't make me think it would be worthwhile, but I'd
X	like to know what you think.
X
X6.	Ideas! Optimizations! Enhancements! Opinions! (On anything
X	other than my indent style)
X
XPlease, I would really like your feedback.  I am but a single
Xprogrammer; you are not (not collectively, anyway).
X
XJohn R. MacMillan
BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM
	set -- `wc -c HelpMe`
	if [ "$1" != "2260" ] ; then
		echo "shar: HelpMe unpacked with wrong size!"
	fi
fi
if [ -f "Makefile" ] ; then
	echo "shar: Will not overwrite existing file Makefile"
else
	echo "shar: extracting Makefile (3262 characters)"
	sed 's/^X//' <<'BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM' > Makefile
X#
X#	Makefile for Yet Another Shared CC driver
X#
X
X# What you want it called, and where to put it:
X
XNAME=	shcc
XBINDIR=	/usr/local/bin
X
X# What to call the library of things missing from the shared C library,
X# and where to put it.
X
XLIBMISSING=	libminic.a
XLIBDIR=		/usr/local/lib
X
X# The pathname of the real cc (normally /bin/cc)
X
XREALCC=	/bin/cc
X
X# If you're going to put LIBMISSING in /lib or /usr/lib (where they
X# can be found by ld(1) with a -l) you can use the first form.  Otherwise
X# stick with the second.
X
X#DEFINES=	-DREALCC=\"$(REALCC)\" -DLIBMISSING=\"-lminic\"
XDEFINES=	-DREALCC=\"$(REALCC)\" -DLIBMISSING=\"$(LIBMISSING)\" \
X		-DLIBMISSINGDIR=\"$(LIBDIR)/\"
X
X# Things missing from the shared version of libc.  I used the same list
X# as is in Jeffery Small's ccc, who did the hard part and figured out
X# what was missing (and he credits Jim Apedaile for the 3.5 stuff).
X# Thanks Jeffery and Jim!
X
XMISSING35=	acct.o assert.o aulrem.o biglitpow.o bsearch.o clrerr.o \
X		doprnt.o doscan.o dtop.o fakcu.o findiop.o hsearch.o \
X	        lfind.o lockf.o lsearch.o ltostr.o mcount.o mon.o ptod.o \
X		setvbuf.o sigrte.o strtod.o sigtrap.o tell.o tfind.o \
X		tsearch.o vfprintf.o vprintf.o vsprintf.o
XMISSING351=	acct.o aulrem.o biglitpow.o clrerr.o doprnt.o doscan.o \
X		dtop.o fakcu.o findiop.o lfind.o lockf.o lsearch.o ltostr.o \
X		mcount.o ptod.o setvbuf.o sigrte.o strtod.o tell.o tfind.o \
X		vfprintf.o vprintf.o vsprintf.o
X
X# Now pick MISSING35 if you're using Version 3.5 of the OS, MISSING351 if
X# you're using version 3.51:
X
X#MISSING=	$(MISSING35)
XMISSING=	$(MISSING351)
X
X# Man page stuff
X
XMAN=	$(NAME).1
XMANDIR=	/usr/man/man1
X
X# Compile time options
X
XCFLAGS=	-O $(DEFINES)
XLDFLAGS=-s
X
X# The shlib.ifile you want "built in" to the driver
X
XIFILE=	/lib/shlib.ifile
X
X# How to install things
X
XINSTALL=	cp
X#INSTALL=	ln
X
X# You shouldn't have to touch these
X
XMYSRCS=	shcc.c options.c passes.c load.c
XSRCS=	$(MYSRCS) ifile.c
XMANFILE=shcc.man
XMISC=	ReadMe HelpMe Makefile $(MANFILE) munge.c
XINCS=	shcc.h
XOBJS=	shcc.o options.o passes.o load.o ifile.o
XLIBS=	-lld
XLIBC=	/lib/libc.a
X
Xall:	$(NAME) $(MAN)
X
X$(NAME):	$(OBJS) $(LIBMISSING)
X		$(LD) $(LDFLAGS) -o $@ /lib/crt0s.o $(OBJS) $(LIBS) \
X			$(LIBMISSING) $(IFILE)
X
Xifile.c:	munge $(IFILE)
X		sed -e '/"/s/"/\\"/g' $(IFILE) | munge > $@
X
X$(OBJS):	$(INCS) Makefile
X
X$(LIBMISSING):	$(LIBC) Makefile
X		ar x $(LIBC) $(MISSING)
X		ar cr $@ $(MISSING)
X		grep daylight $(IFILE) > /dev/null || ( \
X			echo 'int daylight = 1;' > daylight.c ; \
X			$(CC) -c daylight.c ; \
X			ar cr $@ daylight.o \
X		)
X		rm -f $(MISSING) daylight.[co]
X
X$(MAN) man:	$(MANFILE) Makefile
X		echo ".ds Nl \"$(NAME)" > $(MAN)
X		echo ".ds Nu \"`echo $(NAME) | tr '[a-z]' '[A-Z]'`" >> $(MAN)
X		echo ".ds Nm \"`expr $(NAME) : '\(.\).*' | \
X			tr '[a-z]' '[A-Z]'`\c" >> $(MAN)
X		expr $(NAME) : '.\(.*\)' >> $(MAN)
X		echo ".ds Ld \"$(LIBDIR)" >> $(MAN)
X		echo ".ds Ln \"$(LIBMISSING)" >> $(MAN)
X		cat $(MANFILE) >> $(MAN)
X
Xinstall:	$(NAME) $(MAN)
X		$(INSTALL) $(NAME) $(BINDIR)
X		$(INSTALL) $(LIBMISSING) $(LIBDIR)
X		$(INSTALL) $(MAN) $(MANDIR)
X
Xlint:		$(SRCS)
X		lint $(SRCS)
X
Xshar $(NAME).shar:
X		shar $(MISC) $(MYSRCS) $(INCS) > $(NAME).shar
X
Xclean:
X		rm -f $(NAME) munge ifile.c $(OBJS) $(MISSING) \
X		$(LIBMISSING) daylight.[co] $(MAN) *.out core
BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM
	set -- `wc -c Makefile`
	if [ "$1" != "3262" ] ; then
		echo "shar: Makefile unpacked with wrong size!"
	fi
fi
if [ -f "shcc.man" ] ; then
	echo "shar: Will not overwrite existing file shcc.man"
else
	echo "shar: extracting shcc.man (5288 characters)"
	sed 's/^X//' <<'BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM' > shcc.man
X."
X." shcc.man	88/10/20
X."
X.if \*(Nu .ds Nu "SHCC
X.if \*(Nm .ds Nm "Shcc
X.if \*(Nl .ds Nl "shcc
X.if \*(Ld .ds Ld "/usr/local/lib
X.if \*(Ln .ds Ln "libminic.a
X.ifn .ds L" ""
X.ifn .ds R" ""
X.ift .ds L" ``
X.ift .ds R" ''
X.TH \*(Nu 1 LOCAL
X.SH NAME
X\*(Nl \- C compiler using shared libraries
X.SH SYNOPSIS
X.B \*(Nl
X[ option ] ... file ...
X.SH DESCRIPTION
X.I \*(Nm
Xis a compiler similar to the standard
X.IR cc (1)
Xcompiler except it can produce programs which use the shared library.
XIt accepts all the arguments that the standard
X.I cc
Xdoes, including undocumented flags, and behaviour is the same unless
Xnoted here.
XIt also accepts several new flags.
X.PP
XDefault behaviour is to produce an executable that uses the shared
Xlibrary and causes no symbol conflicts.
XThis is accomplished by doing two load passes, and creating a custom ifile
Xlike
X.BR "/lib/shlib.ifile" ,
Xbut containing only necessary symbol definitions.
X.PP
XThe new flags are:
X.IP \-j
XJust like the standard
X.IR cc;
Xdo not use shared libraries.  Only requires one load pass.
X.IP \-q
XQuick compile; do not create a custom ifile, but use
X.BR "/lib/shlib.ifile" ,
Xor the ifile named with the
X.B \-h
Xoption.
XMay cause symbol redefinition errors, but only requires one load pass.
X.IP \-h\fIfile\fP
XIf used with
X.IR \-q ,
Xuse
X.I file
Xinstead of
X.BR /lib/shlib.ifile .
XOtherwise, save the custom ifile that is created in
X.IR file .
X(I know it's not very mnemonic, but we're running low on option
Xletters.  Think of it as
X.RI s h lib
Xfile.)
X.PP
XThe following undocumented options of the standard
X.I cc
Xare supported:
X.IP \-K
XPass the option
X.B \-XK
Xto the compiler pass.  I have no idea what this is for.
X.IP \-X
XUnknown.  If this option is used, the standard
X.I cc
Xis invoked.  Use of this option is incompatible with the \*(L"shared
Xlibrary\*(R" function of
X.IR \*(Nl ,
Xand the options
X.BR \-j , " \-q " ,
Xand
X.BR \-h .
X.IP \-B\fIstring\fP
XConstruct alternate pass names for the preprocessor, compiler,
Xoptimizer, assembler and loader.  If
X.I string
Xis empty it defaults to
X.IR /lib/o .
XIf
X.B \-t
Xis used, the passes named are affected.  Otherwise the passes
X.B p02
Xare affected.  The new pass name is constructed by concatenating
X.I string
Xwith the suffix
X.BR cpp , " ccom" , " optim" ,
X.BR as ,
Xor
X.BR ld ,
Xas appropriate.
X.IP \-t[p012al]
XUse pass names as described for the
X.B \-B
Xoption only for the designated passes.
XIf no
X.B \-B
Xoption is given,
X.I string
Xis taken to be
X.BR /lib/n .
XUsing
X.B \-t """""
Xis equivalent to using
X.BR \-tp012 .
XNote that on the UNIX PC, pass
X.B 0
Xcorresponds to
X.BR ccom ,
Xpass
X.B 2
Xcorresponds to
X.BR optim ,
Xand pass
X.B 1
Xis unused.
X.PP
X.I \*(Nm
Xbehaves slightly differently with respect to the handling of the
X.B \-C
Xoption, which is passed to the preprocessor.  A bug in the standard
X.I cc
Xcauses it to expect an argument following the
X.BR \-C ,
Xbut
X.I \*(Nl
Xdoes not expect this argument.
X.PP
XProfiled objects cannot use the shared library.  Specifying both
X.BR \-p " and " \-q
Xwill cause a warning.
X.PP
XTypical use of the
X.B \-h
Xand
X.B \-q
Xoptions is as follows.
XThe first time a program is compiled,
X.B \-h
Xis used to save the ifile:
X.in +1i
X.B "$ cc \-h my.ifile \-o foobar foo.c bar.c"
X.in -1i
XSubsequent times, this may be used to \*(Lqquickly\*(Rq create foobar:
X.in +1i
X.B "$ cc \-q \-h my.ifile \-o foobar foo.c bar.c"
X.SH FILES
X.nf
Xfile.c                       input file
Xfile.o                       object file
Xfile.s                       assembly language file
Xa.out                        linked output
X/tmp/shcc*                   temporary files
X/lib/cpp                     preprocessor
X/lib/ccom                    compiler
X/lib/optim                   optimizer
X/bin/as                      assembler
X/bin/ld                      link editor
X/lib/crt0.o                  standard startoff
X/lib/crt0s.o                 shared library startoff
X/lib/mcrt0.o                 profiling startoff
X/lib/libc.a                  standard C library
X/lib/lipbp/lib/*.a           profiled versions of libraries
X/lib/shlib.ifile             ifile for shared C library
X\*(Ld/\*(Ln    missing from the shared C library
X.fi
X.SH SEE ALSO
Xcpp(1), as(1), ld(1), prof(1), monitor(3C), shlib(4)
X.SH DIAGNOSTICS
XThe diagnostics should be almost identical to the standard
X.IR cc .
X.SH BUGS
XThe undocumented options were implemented by empirical observation, as
Xwas signal handling, and so may not be identical to the standard
X.IR cc .
X.PP
XThe standard
X.I cc
Xconstructs pass names with the same prefix as its own (if it is called
X.IR prefix cc);
X\*(Nl does not behave this way for obvious reasons.
X.PP
X.I \*(Nm
Xinherits some of the bugs of the original; try
X.in +1i
X.B "cc \-#S foo.s"
X.in -1i
Xfor example.
XThis was done on purpose to emulate the behaviour of the standard
X.I cc
Xas closely as possible, however silly it may be.
X.PP
XHaving said that, the
X.B \-C
Xoption behaves differently.  This one I could not stand, as it's not
Xso esoteric; it affects the
X.IR lint (1)
Xscript!
X.PP
XPlease report any other bugs to the author, if you can find him.
X.SH AUTHOR
XJohn R. MacMillan, currently hanging out at
X.sp
X\&...!watmath!mystic!john
X.br
Xor
X.br
Xjohn%mystic at math.waterloo.edu
X.sp
Xuntil 1989, when I won't be.  If I had to guess for after that, I'd say:
X.br
X{utcsri,utzoo}!hcr!chance!john
BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM
	set -- `wc -c shcc.man`
	if [ "$1" != "5288" ] ; then
		echo "shar: shcc.man unpacked with wrong size!"
	fi
fi
if [ -f "munge.c" ] ; then
	echo "shar: Will not overwrite existing file munge.c"
else
	echo "shar: extracting munge.c (1697 characters)"
	sed 's/^X//' <<'BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM' > munge.c
X/*
X * Munge the /lib/shlib.ifile to produce ifile.c.  Yeah, maybe you could
X * do this with awk or sed or whatever, but by the time I figure out how
X * the C code will be working...
X *
X * Modification History:
X *
X * Release 1.1		88/10/20
X *	Initial release
X */
X
X#ifndef	lint
Xstatic char *SCCS = "@(#)munge.c	1.1	88/10/20";
X#endif
X
X#include <stdio.h>
X
Xstruct	sym	{
X	char	*name;
X	long	addr;
X	struct	sym	*next;
X}
X
Xmain()
X{
X	struct	sym	symlist, *symp;
X	char	line[256], *p, *base;
X	int	inheader = 1;
X	long	baseval;
X	long	value();
X	extern	char	*strchr(), *malloc();
X
X	printf( "#include \"shcc.h\"\n\nchar\t*hdrline[] = {\n" );
X	while( inheader && gets( line ) ) {
X		if( line[0] != ' ' && line[0] != '\t' && strchr(line, '=')) {
X			inheader = 0;
X		} else {
X			printf( "\t\"%s\",\n", line );
X		}
X	}
X	printf( "\t0\n};\n\nstruct\tsymbolentry\tsymtable[] = {\n" );
X
X	symp = &symlist;
X	do {
X		symp->next = (struct sym *)malloc( sizeof(struct sym) );
X		symp = symp->next;
X		p = strchr( line, ' ' );
X		*p = '\0';
X		symp->name = malloc( strlen( line ) );
X		(void) strcpy( symp->name, line );
X		p = strchr( ++p, '=' );
X		p += 2;
X		if( *p == '0' ) {
X			p += 2;
X			sscanf( p, "%lx", &(symp->addr) );
X		} else {
X			base = p;
X			p = strchr( p, ' ' );
X			*p = '\0';
X			baseval = value( symlist.next, base );
X			p = strchr( ++p, '+' );
X			p += 4;
X			sscanf( p, "%lx", &(symp->addr) );
X			symp->addr += baseval;
X		}
X		printf( "\t{ \"%s\", %#lx },\n", symp->name, symp->addr );
X	} while( gets(line) );
X
X	printf( "\t{ 0, 0 }\n};\n" );
X	exit(0);
X}
X
Xlong
Xvalue( symp, sym )
Xstruct	sym	*symp;
Xchar		*sym;
X{
X	while( symp ) {
X		if( !strcmp( symp->name, sym ) )
X			return( symp->addr );
X		symp = symp->next;
X	}
X	return( 0L );
X}
BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM
	set -- `wc -c munge.c`
	if [ "$1" != "1697" ] ; then
		echo "shar: munge.c unpacked with wrong size!"
	fi
fi
if [ -f "shcc.c" ] ; then
	echo "shar: Will not overwrite existing file shcc.c"
else
	echo "shar: extracting shcc.c (6222 characters)"
	sed 's/^X//' <<'BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM' > shcc.c
X/*
X * This is intended to "replace" /bin/cc; it's what (I think) should
X * have been provided in the first place.
X *
X *					John R. MacMillan
X *
X * Modification History:
X *
X * Release 1.1		88/10/20
X *	Initial release
X */
X
X#ifndef	lint
Xstatic char *SCCS = "@(#)shcc.c	1.1	88/10/20";
X#endif
X
X#include "shcc.h"
X#include <stdio.h>
X#include <signal.h>
X#include <varargs.h>
X#include <errno.h>
X
X/*
X * I don't know why this isn't taken care of in stdio.h:
X */
X
X#ifdef	lint
XFILE	_iob2[_NFILE-20];
Xunsigned char *_buf2endtab[];
X#endif	/* lint */
X
X/*
X * Startup files
X */
X
Xchar	*crt0	= "crt0.o",
X	*mcrt0	= "mcrt0.o",
X	*shcrt0	= "crt0s.o",
X	*crtpath;
X
X/*
X * Pass names and paths
X */
X
Xchar	*cpp	= "cpp",
X	*ccom	= "ccom",
X	*ccom20	= "ccom20",
X	*ccom2081 = "ccom20.81",
X	*optim	= "optim",
X	*as	= "as",
X	*ld	= "ld",
X	*cpppath, *ccompath, *optimpath, *aspath, *ldpath, *altpath;
X
X/*
X * Stuff for setting up the argument vectors for each pass
X */
X
Xchar	**cppargv,
X	**ccomargv,
X	**optimargv,
X	**asargv,
X	**ldinargv,
X	**ldoutargv;
X
Xint	cppargc = FIRSTCPP,	cppmax,		cppin,		cppout,
X	ccomargc = 1,		ccommax,	ccomin,		ccomout,
X	optimargc = 1,		optimmax,	optimin,	optimout,
X	asargc = 1,		asmax,		asin,		asout,
X	ldinargc = FIRSTLD,	ldinmax,
X	ldoutargc = FIRSTLD,	ldoutmax;
X
X/*
X * List of input files
X */
X
Xchar	**files;
Xint	numfiles = 0,		maxfiles;
X
X/*
X * Option flags and such
X */
X
Xint	noshlib,		/* -j Don't use shared libraries */
X	quick,			/* -q Use /lib/shlib.ifile */
X	verbose,		/* -v Report on passes */
X	profile,		/* -p Create profiled object */
X	display,		/* -# Just show passes */
X	debug,			/* -g Debuggable object */
X	Ecpp,			/* -E cpp to stdout */
X	Pcpp,			/* -P cpp to .i file */
X	Kflag,			/* -K ??? */
X	givenifile;		/* -i Given ifile to use or create */
X
X					/* Which passes to do */
Xint	passes = PREPROCESS|COMPILE|ASSEMBLE|LOAD;
Xint	altpasses = 0;
X
Xchar	*outfile,			/* ld(1) output file */
X	*ifile = "shlib.ifile",		/* Shared lib ifile */
X	*ifilepath,			/* Path to ifile */
X	*xlibc = LIBMISSING,		/* Lib with missing stuff */
X	*xlibcpath;
X
X/*
X * Temporary files
X */
X
Xchar	*tmp[6];
Xint	numtmp = 0;
X
X/*
X * Miscellaneous
X */
X
Xint	cpu, fpu;
X
Xint	exitstatus = 0;
X
Xchar	*name;
X
Xmain( argc, argv )
Xint	argc;
Xchar	**argv;
X{
X	char	**filep;
X	char	*suffix();
X	void	fatal();
X	extern	char	**AddArg();
X	extern	void	InitStuff(), ParseCmdline(), PrepPasses(),
X			DoPasses(), DoLoad(), CleanUp();
X	extern	char	*getenv(), *strcpy(), *strcat();
X	extern	void	exit();
X
X	name = argv[0];
X
X	/*
X	 * Initialize some stuff and parse the commandline (I know; you
X	 * could have figured that out yourself)
X	 */
X
X	InitStuff();
X	ParseCmdline( argc, argv );
X
X	/*
X	 * Really dumb error check that could be more useful, but I'm
X	 * just doing like they do...
X	 */
X
X	files = AddArg( NULL, files, &numfiles, &maxfiles );
X	numfiles--;
X	if( outfile && *(suffix(outfile)) == 'c' ) {
X		filep = files;
X		while( *filep ) {
X			if( !strcmp( *filep, outfile ) )
X				fatal( 8, "-o would overwrite %s", outfile );
X			filep++;
X		}
X	}
X
X	/*
X	 * Check that the cpu and fpu make a legal combo, and if so put
X	 * the info into the environment
X	 */
X
X	if( fpu == 68881 && cpu != 68020 )
X		fatal( 1, "illegal 68881/68000/68010 combination" );
X	else if ( fpu == 68881 )
X		(void) putenv( "CENVIRON=CPU=68020,FPU=68881" );
X	else if ( cpu == 68020 )
X		(void) putenv( "CENVIRON=CPU=68020" );
X	else if ( cpu == 68000 )
X		(void) putenv( "CENVIRON=CPU=68000" );
X	else
X		(void) putenv( "CENVIRON=CPU=68010" );
X
X	/*
X	 * And a silly error check of my own...
X	 */
X
X	if( profile && quick )
X		warn( "%s:  Warning, profiled programs cannot use shared library\n", name );
X
X
X	/*
X	 * Set up for the preliminary passes, and do them on each input
X	 * file
X	 */
X
X	if( ldinargc == FIRSTLD && ldoutargc == FIRSTLD )
X		passes &= ~LOAD;
X	if( numfiles == 0 )
X		passes &= LOAD;
X	PrepPasses();
X	filep = &files[0];
X	while( *filep )
X		DoPasses( *filep++ );
X
X	/*
X	 * If we're still kicking, let's load the sucker
X	 */
X
X	if( passes & LOAD )
X		DoLoad();
X
X	CleanUp();
X
X	exit( exitstatus );
X
X	/*NOTREACHED*/
X}
X
X/*
X * Execute an individual pass, given the same args that execv() expects
X */
X
Xint
Xcallsys( path, argv )
Xchar	*path;
Xchar	**argv;
X{
X	int	pid;
X	int	status;
X	extern	int	errno;
X	extern	int	fork(), execv(), wait();
X
X	if( display ) {
X		status = 0;
X		(void) printf( "callsys %s:", path );
X		while(*argv)
X			(void) printf( " '%s'", *argv++ );
X		(void) putchar( '\n' );
X	} else {
X		pid = fork();
X		switch( pid ) {
X		case -1:
X			fatal( 1, "No more processes" );
X			break;
X		case 0:
X			(void) execv( path, argv );
X			fatal( 1, "Can't find %s", path );
X			break;
X		default:
X			status = 1;
X			while( wait( &status ) == -1 && errno == EINTR )
X				;
X			break;
X		}
X	}
X
X	return( status );
X}
X
X/*
X * Cheesy allocation for strings.  No provision for ever freeing the
X * space, but, hey, it's only a cc driver
X */
X
Xchar *
Xstralloc( len )
Xint	len;
X{
X	static	int	remaining = 0;
X	static	char	*strbuf = NULL;
X	char	*p;
X	extern	char	*malloc();
X
X	if( ++len > remaining ) {
X		remaining = STRCHUNK;
X		strbuf = malloc( (unsigned) STRCHUNK );
X	}
X	if( !strbuf )
X		fatal( 1, "out of memory(stralloc)" );
X	p = strbuf;
X	strbuf += len;
X	remaining -= len;
X
X	return( p );
X}
X
X/*
X * Return a pointer to the suffix portion of a file name, or NULL if
X * none found
X */
X
Xchar *
Xsuffix( file )
Xchar	*file;
X{
X	char	*sfx;
X	extern	char	*strrchr();
X
X	sfx = strrchr( file, '.' );
X	if( !sfx || !*++sfx )
X		sfx = NULL;
X
X	return( sfx );
X}
X
X/*
X * Print fatal error message and die.  Format is:
X *	fatal( exitstatus, fmt, arg, arg, ... );
X */
X
X#ifdef	lint
X#undef	va_arg
X#define	va_arg(x,cast)	(cast) 0
X#endif	/* lint */
X
X/*VARARGS*/
Xvoid
Xfatal( va_alist )
Xva_dcl
X{
X	va_list	args;
X	int	status;
X	char	*fmt;
X	void	CleanUp();
X
X	va_start(args);
X	status = va_arg(args, int);
X	fmt = va_arg(args, char *);
X	(void) printf( "%s:  ", name );
X	(void) vprintf( fmt, args );
X	(void) putchar( '\n' );
X	va_end(args);
X
X	CleanUp();
X
X	exit(status);
X}
X
X/*
X * Blow away the temp files
X */
X
Xvoid
XCleanUp()
X{
X	extern	int	unlink();
X
X	while( numtmp )
X		(void) unlink( tmp[--numtmp] );
X
X	return;
X}
X
Xint
XSigCatch( signum )
Xint	signum;
X{
X	(void) signal( SIGINT, SIG_IGN );
X	(void) signal( SIGTERM, SIG_IGN );
X
X	CleanUp();
X
X	exit( (signum == SIGINT) ? INTEXIT : TERMEXIT );
X
X	/*NOTREACHED*/
X}
BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM
	set -- `wc -c shcc.c`
	if [ "$1" != "6222" ] ; then
		echo "shar: shcc.c unpacked with wrong size!"
	fi
fi
if [ -f "options.c" ] ; then
	echo "shar: Will not overwrite existing file options.c"
else
	echo "shar: extracting options.c (7617 characters)"
	sed 's/^X//' <<'BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM' > options.c
X/*
X * Option parsing stuff
X *
X * Modification History:
X *
X * Release 1.1		88/10/20
X *	Initial release
X */
X
X#ifndef	lint
Xstatic char *SCCS = "@(#)options.c	1.1	88/10/20";
X#endif
X
X#include "shcc.h"
X#include <stdio.h>
X
Xvoid
XParseCmdline( argc, argv )
Xint	argc;
Xchar	**argv;
X{
X	int	opt, processor;
X	char	*p, passchar;
X	char	**AddArg();
X	void	AddLdArg(), ParseWargs();
X	extern	char	*stralloc(), *suffix(); 
X	extern	void	fatal(), exit();
X	extern	char	*optarg;
X	extern	int	optind, opterr, optopt;
X	extern	char	*strchr(), *strcpy();
X	extern	int	execv();
X
X	/*
X	 * Parse the options
X	 */
X
X	opterr = 0;
X	while( optind < argc ) {
X		while( (opt = getopt( argc, argv, OPTIONS )) != EOF ) {
X			switch( opt ) {
X			case 'j':
X				noshlib++;
X				break;
X			case 'q':
X				quick++;
X				break;
X			case 'v':
X				verbose++;
X				break;
X			case 'p':
X				profile++;
X				noshlib++;
X				ldinargv = AddArg( "-L/lib/libp", ldinargv,
X						&ldinargc, &ldinmax );
X				break;
X			case 'S':
X				passes &= (PREPROCESS|COMPILE);
X				break;
X			case 'T':
X				cppargv = AddArg( "-T", cppargv, &cppargc,
X						&cppmax );
X				ccomargv = AddArg( "-XT", ccomargv,
X						&ccomargc, &ccommax );
X				asargv = AddArg( "-T", asargv, &asargc,
X						&asmax );
X				ldinargv = AddArg( "-G", ldinargv,
X						&ldinargc, &ldinmax );
X				ldoutargv = AddArg( "-G", ldoutargv,
X						&ldoutargc, &ldoutmax );
X				break;
X			case 'o':
X				if( !optarg || !*optarg )
X					fatal( 8, "No output file found for '-o' option\n" );
X				outfile = optarg;
X				break;
X			case 'O':
X				if( debug )
X					warn( "%s:  Warning, -g overrides -O\n", name );
X				else if( passes & COMPILE )
X					passes |= OPTIMIZE;
X				break;
X			case '#':
X				display++;
X				break;
X			case 'g':
X				if( passes & OPTIMIZE ) {
X					passes &= ~OPTIMIZE;
X					warn( "%s:  Warning, -g overrides -O\n", name );
X				}
X				debug++;
X				ccomargv = AddArg( "-g", ccomargv, &ccomargc,
X						&ccommax );
X				break;
X			case 'E':
X				Ecpp++;
X				passes = PREPROCESS;
X				break;
X			case 'P':
X				Pcpp++;
X				passes = PREPROCESS;
X				break;
X			case 'c':
X				passes &= ~LOAD;
X				break;
X			case 'D':
X			case 'I':
X			case 'U':
X				p = stralloc(strlen(optarg) + 2);
X				*p++ ='-';
X				*p++ = (char) opt;
X				*p = '\0';
X				if( optarg )
X					(void) strcpy( p, optarg );
X				cppargv = AddArg( p - 2, cppargv,
X						&cppargc, &cppmax );
X				break;
X			case 'C':
X				cppargv = AddArg( "-C", cppargv,
X						&cppargc, &cppmax );
X				break;
X			case 'K':
X				Kflag++;
X				break;
X			case 'i':
X				givenifile++;
X				ifile = optarg;
X				break;
X			case '6':
X				processor = 60000 + atoi( optarg );
X				switch( processor ) {
X				case 68000:
X				case 68010:
X				case 68020:
X					cpu = processor;
X					break;
X				case 68881:
X					fpu = processor;
X					break;
X				default:
X					fatal( 1, "illegal -6????, target flag" );
X					break;
X				}
X				break;
X			case 'X':
X				(void) execv( REALCC, argv );
X				fatal( 1, "Can't find %s", REALCC );
X				/*NOTREACHED*/
X				break;
X			case 'l':
X			case 'L':
X				p = stralloc(strlen(optarg) + 2);
X				*p++ ='-';
X				*p++ = (char) opt;
X				*p = '\0';
X				if( optarg )
X					(void) strcpy( p, optarg );
X				ldinargv = AddArg( p - 2, ldinargv,
X						&ldinargc, &ldinmax );
X				break;
X			case '?':
X				p = stralloc(2);
X				*p++ = '-';
X				*p++ = (char) optopt;
X				*p = '\0';
X				AddLdArg( p - 2 );
X				break;
X			case 'W':
X				if( !optarg ) {
X					p = "-W";
X					ldinargv = AddArg( p, ldinargv,
X							&ldinargc, &ldinmax );
X					ldoutargv = AddArg( p, ldoutargv,
X							&ldoutargc, &ldoutmax );
X				} else {
X					passchar = *optarg;
X					p = strchr( optarg, ',' );
X					if( !p ) {
X						warn( "%s:  Invalid subargument: -W%s\n", name, optarg );
X						passes = 0;
X						exitstatus = 1;
X					} else {
X						ParseWargs( passchar, p+1 );
X					}
X				}
X				break;
X			case 'B':
X				if(!altpasses)
X					altpasses = PREPROCESS|COMPILE|OPTIMIZE;
X				if( optarg && *optarg )
X					altpath = optarg;
X				else
X					altpath = "/lib/o";
X				break;
X			case 't':
X				if( !altpath )
X					altpath = "/lib/n";
X				p = optarg;
X				if( !p || !*p )
X					p = "p012";
X				altpasses = 0;
X				while(*p) {
X					switch (*p++) {
X					case 'p':
X						altpasses |= PREPROCESS;
X						break;
X					case '0':
X						altpasses |= COMPILE;
X						break;
X					case '1':
X						break;
X					case '2':
X						altpasses |= OPTIMIZE;
X						break;
X					case 'a':
X						altpasses |= ASSEMBLE;
X						break;
X					case 'l':
X						altpasses |= LOAD;
X						break;
X					default:
X						break;
X					}
X				}
X				break;
X			}
X		}
X
X		/*
X		 * File arguments.  If they are a .c or a .s file, put
X		 * the corresponding .o on the ld arg list, otherwise,
X		 * put the file on unaltered.
X		 */
X
X		while((optind < argc) && (*argv[optind] != '-')) {
X			files = AddArg( argv[optind], files, &numfiles,
X					&maxfiles );
X			p = suffix( files[numfiles-1] );
X			if( p && !*(p+1) && (*p == 'c' || *p == 's') ) {
X				p = stralloc( strlen(files[numfiles-1]) );
X				(void) strcpy( p, files[numfiles-1] );
X				ldinargv = AddArg( p, ldinargv, &ldinargc,
X						&ldinmax );
X				p = suffix( p );
X				*p = 'o';
X			} else {
X				ldinargv = AddArg( files[numfiles-1],
X					ldinargv, &ldinargc, &ldinmax );
X			}
X			optind++;
X		}
X	}
X}
X
X/*
X * Add an argument to an argument vector, snagging more space if
X * necessary
X */
X
Xchar **
XAddArg( arg, argv, argc, max )
Xchar	*arg;
Xchar	**argv;
Xint	*argc;
Xint	*max;
X{
X	extern	char	*malloc(), *realloc();
X	extern	void	free();
X
X	if( *argc >= *max ) {
X		*max += ARGCHUNK;
X		if( argv ) {
X			free( (char *) argv );
X			argv = (char **) realloc( (char *) argv,
X				(*max * sizeof(char *)) );
X		} else {
X			argv = (char **) malloc( (*max * sizeof(char *)) );
X		}
X		if( !argv )
X			fatal( 1, "out of memory(AddArg)" );
X	}
X	argv[ (*argc)++ ] = arg;
X
X	return( argv );
X}
X
X/*
X * Add an arg to the appropriate ld(1) pass(es)
X */
X
Xvoid
XAddLdArg( arg )
Xchar	*arg;
X{
X	char	*ch;
X
X	ch = arg + 1;
X	if( *ch == 'V' && *++ch == 'S' ) {
X		ldoutargv = AddArg( arg, ldoutargv, &ldoutargc,
X				&ldoutmax );
X	} else if( strchr( LDOUTARGS, *ch ) ) {
X		ldoutargv = AddArg( arg, ldoutargv, &ldoutargc,
X				&ldoutmax );
X	} else if( strchr( LDINARGS, *ch ) ) {
X		ldinargv = AddArg( arg, ldinargv, &ldinargc,
X				&ldinmax );
X	} else {
X		ldoutargv = AddArg( arg, ldoutargv, &ldoutargc,
X				&ldoutmax );
X		ldinargv = AddArg( arg, ldinargv, &ldinargc,
X				&ldinmax );
X	}
X}
X
X/*
X * Parse the string accomanying a -W option
X */
X
Xvoid
XParseWargs( pass, args )
Xchar	pass;
Xchar	*args;
X{
X	char	**CommaArgs();
X
X	switch( pass ) {
X	case 'p':
X		cppargv = CommaArgs( pass, cppargv, args, &cppargc, &cppmax );
X		break;
X	case '0':
X		ccomargv = CommaArgs( pass, ccomargv, args, &ccomargc,
X				&ccommax );
X		break;
X	case '1':
X		break;
X	case '2':
X		optimargv = CommaArgs( pass, optimargv, args, &optimargc,
X				&optimmax );
X		break;
X	case 'a':
X		asargv = CommaArgs( pass, asargv, args, &asargc, &asmax );
X		break;
X	case 'l':
X		(void) CommaArgs( pass, NULL, args, NULL, NULL );
X		break;
X	default:
X		warn( "%s:  Unrecognized pass name: '-W%c'\n", name, pass );
X		passes = 0;
X		exitstatus = 1;
X	}
X}
X
X/*
X * Parse the comma-separated list of args and add them to the argument
X * vector argv.  If pass is 'l', add the args to the appropriate ld arg
X * vector
X */
X
Xchar **
XCommaArgs( pass, argp, args, argc, max )
Xchar	pass;
Xchar	**argp;
Xchar	*args;
Xint	*argc;
Xint	*max;
X{
X	char	*p;
X	char	**AddArg();
X	void	AddLdArg();
X	extern	char	*strchr();
X
X	while( p = strchr( args, ',' ) ) {
X		*p = '\0';
X		if( pass == 'l' )
X			AddLdArg( args );
X		else
X			argp = AddArg( args, argp, argc, max );
X		args = p + 1;
X	}
X	if( *args ) {
X		if( pass == 'l' )
X			AddLdArg( args );
X		else
X			argp = AddArg( args, argp, argc, max );
X	}
X
X	return( argp );
X}
BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM
	set -- `wc -c options.c`
	if [ "$1" != "7617" ] ; then
		echo "shar: options.c unpacked with wrong size!"
	fi
fi
if [ -f "passes.c" ] ; then
	echo "shar: Will not overwrite existing file passes.c"
else
	echo "shar: extracting passes.c (7807 characters)"
	sed 's/^X//' <<'BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM' > passes.c
X/*
X * Routines to prepare and execute the "preliminary passes": cpp, ccom,
X * optim, and as
X *
X * Modification History:
X *
X * Release 1.1		88/10/20
X *	Initial release
X */
X
X#ifndef	lint
Xstatic char *SCCS = "@(#)passes.c	1.1	88/10/20";
X#endif
X
X#include "shcc.h"
X#include <stdio.h>
X#include <signal.h>
X
X/*
X * As the name says, initialize some stuff.
X */
X
Xvoid
XInitStuff()
X{
X	char	*cenviron, *ccroot;
X	int	len;
X	void	SetPU();
X	extern	char	*stralloc();
X	extern	int	SigCatch();
X	extern	char	*getenv(), *strcat(), *strcpy();
X
X	/*
X	 * Set up signal catching routine
X	 */
X
X	if( signal( SIGINT, SigCatch ) == SIG_IGN )
X		(void) signal( SIGINT, SIG_IGN );
X	if( signal( SIGTERM, SigCatch ) == SIG_IGN )
X		(void) signal( SIGTERM, SIG_IGN );
X
X	/*
X	 * If there's a CENVIRON variable, parse it to set the cpu and
X	 * fpu
X	 */
X
X	if( (cenviron = getenv( "CENVIRON" )) && *cenviron )
X		SetPU( cenviron, "CENVIRON" );
X	else {
X		cpu = DEFAULTCPU;
X		fpu = SOFTWARE;
X	}
X
X	/*
X	 * Set up default paths for passes
X	 */
X
X	if( (ccroot = getenv("CCROOT")) && *ccroot ) {
X		len = strlen( ccroot );
X		cpppath = ccompath = optimpath = crtpath = ifilepath =
X			stralloc((int)(len + sizeof(LIBDIR)));
X		(void) strcat( strcpy(cpppath, ccroot), LIBDIR );
X		aspath = ldpath = stralloc((int)(len + sizeof(BINDIR)));
X		(void) strcat( strcpy(aspath, ccroot), LIBDIR );
X		xlibcpath = stralloc((int)(len + sizeof(LIBMISSINGDIR)));
X		(void) strcat( strcpy(xlibcpath, ccroot), LIBMISSINGDIR );
X	} else {
X		cpppath = ccompath = optimpath = crtpath = ifilepath = LIBDIR;
X		aspath = ldpath = BINDIR;
X		xlibcpath = LIBMISSINGDIR;
X	}
X}
X
X/*
X * Set the cpu and fpu from the given string
X */
X
Xvoid
XSetPU( cenviron, var )
Xchar	*cenviron;
Xchar	*var;
X{
X	char	*p, pu, wanted;
X	extern	void	fatal();
X	extern	int	atoi();
X	extern	char	*strtok();
X
X	cpu = DEFAULTCPU;
X	fpu = SOFTWARE;
X	wanted = 'X';
X	p = strtok( cenviron, ", \t" );
X	do {
X		pu = *p++;
X		if( pu == 'C' && wanted != 'F'
X			&& *p++ == 'P' && *p++ == 'U' && *p++ == '=' ) {
X			cpu = atoi( p );
X			if( cpu != 68000 && cpu != 68010 && cpu != 68020 ) {
X				warn( "%s: bad cpu (%s) in %s ignored, default: %d\n", name, p, var, DEFAULTCPU );
X				cpu = DEFAULTCPU;
X			}
X			if( wanted == 'F' )
X				wanted = '\0';
X			else
X				wanted = 'F';
X		} else if( pu == 'F' && wanted != 'C'
X			&& *p++ == 'P' && *p++ == 'U' && *p++ == '=' ) {
X			fpu = atoi( p );
X			if( fpu != 68881 ) {
X				if( fpu == 0 && strcmp(p, "SOFTWARE") )
X					warn( "%s: bad fpu (%s) in %s ignored, default: SOFTWARE\n", name, p, var );
X				fpu = SOFTWARE;
X			}
X			if( wanted == 'F' )
X				wanted = '\0';
X			else
X				wanted = 'C';
X		}
X	} while( wanted && (p = strtok( NULL, ", \t" )) );
X
X	if( fpu == 68881 && cpu != 68020 )
X		fatal( 1, "incompatiable combination of fpu/cpu in %s", var );
X}
X
X/*
X * Prep the argument vectors for each pass, filling in any extra args,
X * temp file names, etc.
X */
X
Xvoid
XPrepPasses()
X{
X	int	argc;
X	extern	char	**AddArg();
X	extern	char	*tempnam();
X
X	/*
X	 * Cpp.  Temp file or - for output
X	 */
X
X	cppin = cppargc++;
X	cppout = cppargc++;
X	cppargv = AddArg( NULL, cppargv, &cppargc, &cppmax );
X	argc = FIRSTCPP - 1;
X	if( cpu == 68020 )
X		cppargv[argc--] = "-Dmc68020";
X	else
X		cppargv[argc--] = "-Dmc68010";
X	if( fpu == 68881 )
X		cppargv[argc--] = "-Dmc68881";
X	cppargv[argc--] = "-Dmc68k";
X	cppargv[argc--] = "-Dmc68k32";
X	if( argc ) {
X		cppargv = &cppargv[ argc ];
X		cppin -= argc;
X		cppout -= argc;
X		cppargc -=argc;
X		cppmax -= argc;
X	}
X	if( Ecpp )
X		cppargv[cppout] = "-";
X	else {
X		tmp[ numtmp++ ] = cppargv[cppout] = tempnam( TMPDIR, TMPFX );
X	}
X
X	/*
X	 * Ccom
X	 */
X
X	if( passes & COMPILE ) {
X		if( fpu == 68881 )
X			ccom = ccom2081;
X		else if( cpu == 68020 )
X			ccom = ccom20;
X		ccomin = ccomargc++;
X		ccomout = ccomargc++;
X		if( profile )
X			ccomargv = AddArg( "-XP", ccomargv, &ccomargc,
X				&ccommax );
X		if( Kflag )
X			ccomargv = AddArg( "-XK", ccomargv, &ccomargc,
X				&ccommax );
X		ccomargv = AddArg( NULL, ccomargv, &ccomargc, &ccommax );
X		ccomargv[ccomin] = cppargv[cppout];
X		if( passes & (OPTIMIZE|ASSEMBLE) ) {
X			ccomargv[ccomout] = tempnam( TMPDIR, TMPFX );
X			tmp[ numtmp++ ] = ccomargv[ccomout];
X		}
X	}
X
X	/*
X	 * Optimizer
X	 */
X
X	if( passes & OPTIMIZE ) {
X		optimargv = AddArg( NULL, optimargv, &optimargc, &optimmax );
X		optimin = 1;
X		optimout = 2;
X		optimargv[optimin] = ccomargv[ccomout];
X		if( passes & ASSEMBLE ) {
X			optimargv[optimout] = tempnam( TMPDIR, TMPFX );
X			tmp[ numtmp++ ] = optimargv[optimout];
X		}
X	}
X
X	/*
X	 * Assembler.  Note we always set up for the assembler so that
X	 * the "feature" that if you give -S foo.s it assembles foo.s to
X	 * foo.o
X	 */
X
X	asargv = AddArg( "-C", asargv, &asargc, &asmax );
X	asargv = AddArg( "-o", asargv, &asargc, &asmax );
X	asout = asargc++;
X	asin = asargc++;
X	asargv = AddArg( NULL, asargv, &asargc, &asmax );
X	asargv[asin] = (passes & OPTIMIZE) ? optimargv[optimout] :
X			ccomargv[ccomout];
X}
X
X/*
X * Execute the preliminary (non-load) passes on a given file
X */
X
Xvoid
XDoPasses( file )
Xchar	*file;
X{
X	int	reqdpasses;
X	char	*sfx, *tmpas, *path;
X	extern	char	*suffix(), *stralloc();
X	extern	int	callsys();
X	extern	int	strlen();
X	extern	char	*strcpy(), *strcat();
X
X	tmpas = NULL;
X	sfx = suffix( file );
X	if( !sfx || *(sfx + 1) )
X		return;
X	if( *sfx == 'c' ) {
X		reqdpasses = passes;
X		cppargv[cppin] = file;
X	} else if( *sfx == 's' ) {
X		if( Ecpp || Pcpp ) {
X			reqdpasses = passes;
X			cppargv[cppin] = file;
X		} else {
X			/*
X			 * You know and I know that this next line should
X			 * be ~(PREPROCESS|COMPILE|OPTIMIZE), but
X			 * whoever wrote /bin/cc didn't
X			 */
X			reqdpasses = ASSEMBLE;
X			tmpas = asargv[asin];
X			asargv[asin] = file;
X		}
X	} else {
X		return;
X	}
X
X	if( numfiles > 1 )
X		(void) printf( "%s:\n", file );
X
X	if( reqdpasses & PREPROCESS ) {
X		if( verbose )
X			(void) printf( "Preprocessing ...\n" );
X		if( Pcpp && !Ecpp ) {
X			cppargv[cppout] = stralloc( strlen(file) );
X			(void) strcpy( cppargv[cppout], file );
X			*(suffix(cppargv[cppout])) = 'i';
X		}
X		if( altpasses & PREPROCESS )
X			cpppath = altpath;
X		path = stralloc( strlen(cpppath) + strlen(cpp) );
X		(void) strcat( strcpy( path, cpppath ), cpp );
X		cppargv[0] = cpp;
X		if( callsys( path, cppargv ) ) {
X			reqdpasses = 0;
X			passes &= ~LOAD;
X			exitstatus = 1;
X		}
X	}
X
X	if( reqdpasses & COMPILE ) {
X		if( verbose )
X			(void) printf( "Compiling ...\n" );
X		if(!(reqdpasses & (OPTIMIZE|ASSEMBLE))) {
X			ccomargv[ccomout] = stralloc( strlen(file) );
X			(void) strcpy( ccomargv[ccomout], file );
X			*(suffix(ccomargv[ccomout])) = 's';
X		}
X		if( altpasses & COMPILE )
X			ccompath = altpath;
X		path = stralloc( strlen(ccompath) + strlen(ccom) );
X		(void) strcat( strcpy( path, ccompath ), ccom );
X		ccomargv[0] = ccom;
X		if( callsys( path, ccomargv ) ) {
X			reqdpasses = 0;
X			passes &= ~LOAD;
X			exitstatus = 1;
X		}
X	}
X
X	if( reqdpasses & OPTIMIZE ) {
X		if( verbose )
X			(void) printf( "Optimizing ...\n" );
X		if(!(reqdpasses & ASSEMBLE)) {
X			optimargv[optimout] = stralloc( strlen(file) );
X			(void) strcpy( optimargv[optimout], file );
X			*(suffix(optimargv[optimout])) = 's';
X		}
X		if( altpasses & OPTIMIZE )
X			optimpath = altpath;
X		path = stralloc( strlen(optimpath) + strlen(optim) );
X		(void) strcat( strcpy( path, optimpath ), optim );
X		optimargv[0] = optim;
X		if( callsys( path, optimargv ) ) {
X			reqdpasses = 0;
X			passes &= ~LOAD;
X			exitstatus = 1;
X		}
X	}
X
X	if( reqdpasses & ASSEMBLE ) {
X		if( verbose )
X			(void) printf( "Assembling ...\n" );
X		asargv[asout] = stralloc( strlen(file) );
X		(void) strcpy( asargv[asout], file );
X		*(suffix(asargv[asout])) = 'o';
X		if( altpasses & ASSEMBLE )
X			aspath = altpath;
X		path = stralloc( strlen(aspath) + strlen(as) );
X		(void) strcat( strcpy( path, aspath ), as );
X		asargv[0] = as;
X		if( callsys( path, asargv )  ) {
X			reqdpasses = 0;
X			passes &= ~LOAD;
X			exitstatus = 1;
X		}
X	}
X	if( tmpas )
X		asargv[asin] = tmpas;
X}
BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM
	set -- `wc -c passes.c`
	if [ "$1" != "7807" ] ; then
		echo "shar: passes.c unpacked with wrong size!"
	fi
fi
if [ -f "load.c" ] ; then
	echo "shar: Will not overwrite existing file load.c"
else
	echo "shar: extracting load.c (7243 characters)"
	sed 's/^X//' <<'BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM' > load.c
X/*
X * Stuff to do the load pass (or passes)
X *
X * Modification History:
X *
X * Release 1.1		88/10/20
X *	Initial release
X */
X
X#ifndef	lint
Xstatic char *SCCS = "@(#)load.c	1.1	88/10/20";
X#endif
X
X#include "shcc.h"
X#include <stdio.h>
X#include <filehdr.h>
X#include <syms.h>
X#include <ldfcn.h>
X
X/*
X * Some stuff for lint, since we don't have a lint library for libld.a
X */
X
X#ifdef	lint
X#undef	FSEEK
X/*ARGSUSED*/
Xlong	FSEEK( l, o, w ) LDFILE *l; long o; int w; { return 0L; }
X/*ARGSUSED*//* Sleaziness to avoid a few lint messages */
XLDFILE	*ldopen( f, l ) char *f; LDFILE *l; { _iob2[0]=_iob[0];
X	_buf2endtab[0]=NULL; return ldaopen(f,l); }
X/*ARGSUSED*/
XLDFILE	*ldaopen( f, l ) char *f; LDFILE *l; { return (LDFILE *)NULL; }
X/*ARGSUSED*/
Xint	ldtbread( l, i, s ) LDFILE *l; long i; SYMENT *s; { return 0; }
X/*ARGSUSED*/
Xint	ldclose( l ) LDFILE *l; { return 0; }
X#endif	/* lint */
X
Xvoid
XDoLoad()
X{
X	char	*path, *tmpld = NULL;
X	char	*sfx;
X	int	argc;
X	extern	char	**AddArg();
X	extern	char	*stralloc(), *suffix();
X	extern	int	callsys();
X	extern	void	fatal();
X	extern	char	*strcpy(), *strcat(), *tempnam();
X	extern	int	strlen(), unlink();
X
X	if( verbose )
X		(void) printf( "Loading ...\n" );
X
X	/*
X	 * Finish of arguments on the tail end
X	 */
X
X	if( noshlib || quick ) {
X		/*
X		 * Only one ld(1) pass
X		 */
X		argc = FIRSTLD;
X		while( argc < ldinargc )
X			ldoutargv = AddArg( ldinargv[argc++], ldoutargv,
X					&ldoutargc, &ldoutmax );
X		if( noshlib ) {
X			ldoutargv = AddArg( "-lc", ldoutargv,
X					&ldoutargc, &ldoutmax );
X		} else {
X			if( *xlibc == '-' ) {
X				ldoutargv = AddArg( xlibc, ldoutargv,
X						&ldoutargc, &ldoutmax );
X			} else {
X				path = stralloc( strlen(xlibcpath) +
X						strlen(xlibc) );
X				(void) strcat( strcpy(path,xlibcpath), xlibc );
X				ldoutargv = AddArg( path, ldoutargv,
X						&ldoutargc, &ldoutmax );
X			}
X			if( givenifile ) {
X				ldoutargv = AddArg( ifile, ldoutargv,
X						&ldoutargc, &ldoutmax );
X			} else {
X				path = stralloc( strlen(ifilepath) + strlen(ifile) );
X				(void) strcat( strcpy(path,ifilepath), ifile );
X				ldoutargv = AddArg( path, ldoutargv,
X						&ldoutargc, &ldoutmax );
X			}
X		}
X		ldoutargv = AddArg( NULL, ldoutargv, &ldoutargc, &ldoutmax );
X
X		argc = FIRSTLD - 1;
X		if( outfile && *outfile ) {
X			ldoutargv[argc--] = outfile;
X			ldoutargv[argc--]= "-o";
X		}
X		if( profile ) {
X			crt0 = mcrt0;
X		} else if ( quick ) {
X			crt0 = shcrt0;
X		}
X		ldoutargv[argc] = stralloc( strlen( crtpath ) +
X			strlen( crt0 ) );
X		(void) strcat( strcpy(ldoutargv[argc--], crtpath), crt0 );
X
X		ldoutargv[argc] = ld;
X		if( altpasses & LOAD )
X			ldpath = altpath;
X		path = stralloc( strlen(ldpath) + strlen(ld) );
X		(void) strcat( strcpy( path, ldpath ), ld );
X
X		if( callsys( path, &ldoutargv[argc] ) )
X			exitstatus = 1;
X
X	} else {
X		/*
X		 * Two pass version
X		 */
X
X		if( debug )
X			ldinargv = AddArg( "-lg", ldinargv,
X					&ldinargc, &ldinmax );
X		if( *xlibc == '-' ) {
X			ldinargv = AddArg( xlibc, ldinargv,
X					&ldinargc, &ldinmax );
X		} else {
X			path = stralloc( strlen(xlibcpath) +
X					strlen(xlibc) );
X			(void) strcat( strcpy(path,xlibcpath), xlibc );
X			ldinargv = AddArg( path, ldinargv,
X					&ldinargc, &ldinmax );
X		}
X		ldinargv = AddArg( NULL, ldinargv, &ldinargc, &ldinmax );
X
X		argc = FIRSTLD - 1;
X		tmp[ numtmp++ ] = tmpld = tempnam( TMPDIR, TMPFX );
X		ldinargv[argc--] = tmpld;
X		ldinargv[argc--] = "-o";
X		ldinargv[argc] = stralloc( strlen( crtpath ) +
X			strlen( shcrt0 ) );
X		(void) strcat( strcpy(ldinargv[argc--], crtpath), shcrt0 );
X		ldinargv[argc--] = "-r";
X
X		ldinargv[argc] = ld;
X		if( altpasses & LOAD )
X			ldpath = altpath;
X		path = stralloc( strlen(ldpath) + strlen(ld) );
X		(void) strcat( strcpy( path, ldpath ), ld );
X
X		if( callsys( path, &ldinargv[argc] ) ) {
X			exitstatus = 1;
X		} else {
X			/*
X			 * Second ld(1) pass
X			 */
X			if( !givenifile ) {
X				tmp[ numtmp++ ] = ifile = tempnam( TMPDIR, TMPFX );
X			}
X			if( !display && MakeIfile( tmpld ) )
X				fatal( 1, "unable to make ifile '%s'", ifile );
X			ldoutargv = AddArg( tmpld, ldoutargv,
X						&ldoutargc, &ldoutmax );
X			ldoutargv = AddArg( ifile, ldoutargv,
X						&ldoutargc, &ldoutmax );
X			ldoutargv = AddArg( NULL, ldoutargv,
X						&ldoutargc, &ldoutmax );
X
X			argc = FIRSTLD - 1;
X			if( outfile && *outfile ) {
X				ldoutargv[argc--] = outfile;
X				ldoutargv[argc--] = "-o";
X			}
X			ldoutargv[argc] = ld;
X
X			if( callsys( path, &ldoutargv[argc] ) )
X				exitstatus = 1;
X		}
X	}
X
X	/*
X	 * Clean up tmp files
X	 */
X
X	if( !display ) {
X		if( tmpld )
X			(void) unlink( tmpld );
X		if( !givenifile && !quick && !noshlib )
X			(void) unlink( ifile );
X		if( numfiles == 1 ) {
X			sfx = suffix(files[0]);
X			if( (*sfx == 's' || *sfx == 'c') && !(*(sfx+1))) {
X				*sfx = 'o';
X				(void) unlink( files[0] );
X			}
X		}
X	}
X
X	return;
X}
X
X/*
X * Make an ifile.  Look through the symbol table of the temporary ld
X * output file and write corresponding ifile lines
X */
X
Xint
XMakeIfile( tmpld )
Xchar	*tmpld;
X{
X	FILE	*iout;
X	LDFILE	*ldin;
X	long	symindex;
X	SYMENT	symbol;
X	char	**p, *thissym;
X	int	i, found;
X	char	*SymbolName();
X	extern	int	ldtbread(), ldclose();
X	extern	LDFILE	*ldopen();
X	extern	char	*hdrline[];
X	extern	struct 	symbolentry	symtable[];
X
X	/*
X	 * Open the tempfile and ifile
X	 */
X
X	if( (ldin = ldopen( tmpld, (LDFILE *)NULL )) == NULL ) {
X		warn( "%s:  unable to open '%s'\n", name, tmpld );
X		return(1);
X	}
X
X	if( (iout = fopen( ifile, "w" )) == NULL ) {
X		warn( "%s:  unable to open '%s' for writing\n", name, ifile );
X		return(1);
X	}
X
X	/*
X	 * Write the header lines
X	 */
X
X	p = &hdrline[0];
X	while( *p ) {
X		(void) fputs( *p++, iout );
X		(void) putc( '\n', iout );
X	}
X
X	/*
X	 * Read the symbol table, if undefined, look it up and write the
X	 * ifile line
X	 */
X
X	symindex = 0L;
X	while( ldtbread( ldin, symindex++, &symbol ) == SUCCESS ) {
X		if( (symbol.n_scnum == N_UNDEF) && (symbol.n_value == 0) ) {
X			thissym = SymbolName( ldin, &symbol );
X			found = i = 0;
X			while( symtable[i].name && !found ) {
X				if( !strcmp( symtable[i].name, thissym ) &&
X					symtable[i].addr ) {
X					(void) fprintf( iout, "%s = %#lx;\n",
X						thissym, symtable[i].addr );
X					symtable[i].addr = 0;
X					found++;
X				}
X				i++;
X			}
X		}
X		symindex += (long) symbol.n_numaux;
X	}
X
X	/*
X	 * Close things up
X	 */
X
X	(void) fclose( iout );
X	(void) ldclose( ldin );
X
X	return(0);
X}
X
X/*
X * Return the name of a symbol given by the SYMENT pointer.  Why don't
X * we have ldgetname() in libld.a, anyway?
X */
X
Xchar *
XSymbolName( ldfile, symptr )
XLDFILE	*ldfile;
XSYMENT	*symptr;
X{
X	static	char	symbuf[ SYMNMLEN + 1];
X	static	char	*stringtable = 0;
X	int		tablesize;
X	char		*sname;
X	long		pos, index;
X	extern	char	*strncpy(), *malloc();
X
X	if( symptr->_n._n_n._n_zeroes != 0L ) {
X		(void) strncpy( symbuf, symptr->n_name, SYMNMLEN );
X		symbuf[ SYMNMLEN + 1 ] = '\0';
X		sname = &symbuf[0];
X	} else {
X		if( !stringtable ) {
X			pos = FTELL( ldfile );
X			(void) FSEEK( ldfile, HEADER(ldfile).f_symptr +
X				HEADER(ldfile).f_nsyms * (long) SYMESZ, 0);
X			index = FTELL( ldfile );
X			tablesize = GETW(ldfile);
X			(void) FSEEK( ldfile, index, 0 );
X			stringtable = malloc( (unsigned) tablesize );
X			(void) FREAD( stringtable, 1, tablesize, ldfile );
X			(void) FSEEK( ldfile, pos, 0 );
X		}
X		index = symptr->_n._n_n._n_offset;
X		sname = stringtable + index;
X	}
X	return( sname );
X}
BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM
	set -- `wc -c load.c`
	if [ "$1" != "7243" ] ; then
		echo "shar: load.c unpacked with wrong size!"
	fi
fi
if [ -f "shcc.h" ] ; then
	echo "shar: Will not overwrite existing file shcc.h"
else
	echo "shar: extracting shcc.h (2401 characters)"
	sed 's/^X//' <<'BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM' > shcc.h
X/*
X * Common include file
X *
X * Modification History:
X *
X * Release 1.1		88/10/20
X *	Initial release
X */
X
X#ifndef	REALCC
X#define	REALCC	"/bin/cc"
X#endif
X
X#ifndef	LIBMISSING
X#define	LIBMISSING	"libminic.a"
X#endif
X#ifndef	LIBMISSINGDIR
X#define	LIBMISSINGDIR	"/usr/local/lib/"
X#endif
X
X#define	ARGCHUNK	20
X#define	STRCHUNK	1024
X#define	OPTIONS		"jqh:vKpSTo:OX#gEPcD:I:U:Ct:B:l:W:6:L:"
X#define	LDINARGS	"ltuLMV"
X#define	LDOUTARGS	"efmorsxZNnzF"
X#define	LIBDIR		"/lib/"
X#define	BINDIR		"/bin/"
X#define	TMPDIR		"/tmp"
X#define	TMPFX		"shcc"
X
X#define	SOFTWARE	0
X#define	DEFAULTCPU	68010
X
X#define	INTEXIT		228
X#define	TERMEXIT	100
X
X#define	warn	(void) printf
X
X#define	PREPROCESS	001
X#define	COMPILE		002
X#define	OPTIMIZE	004
X#define	ASSEMBLE	010
X#define	LOAD		020
X
X/*
X * Startup files
X */
X
Xextern	char	*crt0, *mcrt0, *shcrt0, *crtpath;
X
X/*
X * Pass names and paths
X */
X
Xextern	char	*cpp, *ccom, *ccom20, *ccom2081, *optim, *as, *ld,
X		*cpppath, *ccompath, *optimpath, *aspath, *ldpath,
X		*altpath;
X
X/*
X * Stuff for setting up the argument vectors for each pass
X */
X
Xextern	char	**cppargv,
X		**ccomargv,
X		**optimargv,
X		**asargv,
X		**ldinargv,
X		**ldoutargv;
X
Xextern	int	cppargc,	cppmax,		cppin,		cppout,
X		ccomargc,	ccommax,	ccomin,		ccomout,
X		optimargc,	optimmax,	optimin,	optimout,
X		asargc,		asmax,		asin,		asout,
X		ldinargc,	ldinmax,
X		ldoutargc,	ldoutmax;
X
X#define	FIRSTCPP	5
X#define	FIRSTLD		5
X
X/*
X * List of input files
X */
X
Xextern	char	**files;
Xextern	int	numfiles,		maxfiles;
X
X/*
X * Option flags and such
X */
X
Xextern	int	noshlib,		/* -j Don't use shared libraries */
X		quick,			/* -q Use /lib/shlib.ifile */
X		verbose,		/* -v Report on passes */
X		profile,		/* -p Create profiled object */
X		display,		/* -# Just show passes */
X		debug,			/* -g Debuggable object */
X		Ecpp,			/* -E cpp to stdout */
X		Pcpp,			/* -P cpp to .i file */
X		Kflag,			/* -K ??? */
X		givenifile;		/* -i Given ifile to use or create */
X
X/*
X * Which passes to do
X */
X
Xextern	int	passes;
Xextern	int	altpasses;
X
X/*
X * Some stuff for loading
X */
X
Xextern	char	*outfile,			/* ld(1) output file */
X		*ifile,				/* Shared lib ifile */
X		*ifilepath,			/* Path to ifile */
X		*xlibc,				/* Lib with missing stuff */
X		*xlibcpath;
X
X/*
X * Temporary files
X */
X
Xextern	char	*tmp[];
Xextern	int	numtmp;
X
X/*
X * Miscellaneous
X */
X
Xextern	int	cpu, fpu;
X
Xextern	int	exitstatus;
X
Xextern	char	*name;
X
Xstruct	symbolentry {
X	char	*name;
X	long	addr;
X};
BOP_BOP_A_LOO_WOP_BO_LOP_BAM_BOOM
	set -- `wc -c shcc.h`
	if [ "$1" != "2401" ] ; then
		echo "shar: shcc.h unpacked with wrong size!"
	fi
fi
exit
--
John R. MacMillan			Sometimes you have to go
jrmacmillan at lily.waterloo.edu		for the two in the bush.
..!watmath!lily!jrmacmillan



More information about the Unix-pc.sources mailing list