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