[comp.sources.misc] "mkmf" makefile maker

ljz@fxgrp.UUCP (Lloyd Zusman) (12/26/87)

I hope I am posting this to the right person.  I assume you are
the moderator of comp.sources.misc.

In a recent posting I mentioned a program called "mkmf" which
makes makefiles.  Lots of people have sent me mail requesting
this software, so here it is.  In the aforementioned posting,
I said this program is "netware", but apparently it has not
been posted on the net (???).  It is, however, definitely in
the public domain.

It comes in two pieces.  Here is part 1.

Enjoy.

 Lloyd Zusman
 Master Byte Software
 Los Gatos, California	    	    	Internet:   fxgrp!ljz@ames.arpa
 "We take things well in hand."	    	UUCP:	    ...!ames!fxgrp!ljz

#--------------------------Cut Here--------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before the "#! /bin/sh" line,
# then unpack it by saving it in a file and typing "sh file."
#
# Wrapped by Lloyd Zusman (ljz) at fxgrp on Tue Dec 22 12:53:36 1987
#
# unpacks with default permissions
#
# Contents : Makefile README man/mann/mkmf.n man/mann/Makefile
#	src/Makefile src/Mkmf.c src/badopt.c src/buildlist.c src/depend.c
#	src/dlist.c
#
if `test ! -s Makefile`
then
echo "x - Makefile"
sed 's/^X//' > Makefile << '@\End\of\File\'
XSUBDIR	      = src x.Makefile man/mann
X
XDESTDIR	      =${HOME}
XMANDIR	      =${HOME}/man
X
Xall:		${SUBDIR}
X
X${SUBDIR}:	FRC
X		cd $@; make ${MFLAGS}
X
Xinstall:
X	for i in ${SUBDIR}; do \
X		(cd $$i; make ${MFLAGS} DESTDIR=${DESTDIR} MANDIR=$(MANDIR) install); done
X
Xclean:
X	for i in ${SUBDIR}; do (echo $$i; cd $$i; make ${MFLAGS} clean); done
X
Xdepend:
X	for i in ${SUBDIR}; do (echo $$i; cd $$i; make ${MFLAGS} depend); done
X
XFRC:
@\End\of\File\
else
  echo "shar: Will not over write Makefile"
fi
if `test ! -s README`
then
echo "x - README"
sed 's/^X//' > README << '@\End\of\File\'
XTitle:			mkmf makefile editor
X
XAuthor:			Peter J. Nicklin
X
XAddress:		Hewlett-Packard,
X			Software Engineering Laboratory,
X			3500 Deercreek Road, Building 26U,
X			Palo Alto, California 94304
X
XNet address:		ucbvax!hplabs!hpcea!hpcesea!nicklin (UUCP)
X
XDescription:
X
XThe mkmf makefile editor creates  program and library  makefiles for the
XUNIX make command (UNIX is a trademark of Bell  Telephone  Laboratories,
XInc.).  Mkmf has the following features:
X
X    - Automatically inserts source and object code file names in
X      makefiles
X
X    - Provides standard makefile templates for programs and libraries
X
X    - Allows user-defined makefile templates
X
X    - Generates include file dependencies for C, Pascal, and Fortran
X      source code
X
X    - Allows arbitrary editing of makefiles with a regular text editor
X
XInstallation:
X
X1.	Set up directories  /usr/new,  /usr/new/lib,  and /usr/man/mann.
X	These  must  be writable by the installing process.  If you want
X	to put mkmf somewhere else,  you will have to change  the  DEST=
X	macro in all the makefiles, and edit the "spms.h" file.
X
X2.	Change  to  the  mkmf  directory  and  execute   "make install".
X	If something  goes  wrong, don't panic. Just fix the problem and
X	restart "make install".
X
XBugfixes/Changes:
X
X1.	Mkmf was previously part of the SPMS Software Project Management
X	System. It is now completely independent.
X
X2.	Mkmf now searches for include files in the directory  containing
X	the  file  currently  being  processed,  rather than the current
X	working directory. This only affects nested include files  which
X	are external to the current working directory.
X3.	Mkmf now reads multiple -I options in  CFLAGS  and  FFLAGS  cor-
X	rectly.
X
X4.	Mkmf can now process the example  presented  by  Kim  Walden  in
X	Software-Practice and Experience,  vol. 14,  no. 6, pp. 575-585,
X	June 1984.
@\End\of\File\
else
  echo "shar: Will not over write README"
fi
if `test ! -d man`
then
  mkdir man
  echo "mkdir man"
fi
if `test ! -d man/mann`
then
  mkdir man/mann
  echo "mkdir man/mann"
fi
if `test ! -s man/mann/mkmf.n`
then
echo "x - man/mann/mkmf.n"
sed 's/^X//' > man/mann/mkmf.n << '@\End\of\File\'
X.TH MKMF 1 "28 June 1985"
X.\" $Header: mkmf.n,v 1.8 86/01/12 00:53:14 lepreau Exp $
X.UC 4
X.SH NAME
Xmkmf \- makefile editor
X.SH SYNOPSIS
X.B mkmf
X[\fB\-acdil\fR] [\fB\-f \fRmakefile] [\fB\-F \fRtemplate] [macroname=value ...]
X.SH DESCRIPTION
X.I Mkmf
Xcreates a makefile that tells the
X.I make
Xcommand how to construct and maintain programs and libraries.
XAfter gathering up all the source code file names in the current working
Xdirectory and inserting them into the makefile,
X.I mkmf
Xscans source code files for included
Xfiles and generates dependency information which is appended to the makefile.
XSource code files are identified by their file name suffixes.
X.I Mkmf
Xknows about the following suffixes:
X.LP
X.nf
X.ta 1.5i +1i
X	.c	C
X	.e	Efl
X	.F	Fortran
X	.f	Fortran
X	.h	Include files
X	.i	Pascal include files
X	.l	Lex or Lisp
X	.o	Object files
X	.p	Pascal
X	.r	Ratfor
X	.s	Assembler
X	.y	Yacc
X.fi
X.DT
X.LP
X.I Mkmf
Xchecks for an existing makefile before creating one. If no
X.B \-f
Xoption is present, the makefiles `makefile' and `Makefile' are tried
Xin order.
X.LP
XAfter the makefile has been created, arbitrary changes can be made using
Xa regular text editor.
X.I Mkmf
Xcan also be used to re-edit the macro definitions in the makefile, regardless
Xof changes that may have been made since it was created.
X.LP
XBy default,
X.I mkmf
Xcreates a program makefile. To create a makefile that deals with libraries,
Xthe
X.B \-l
Xoption must be used.
X.LP
X\fBMake Requests\fR
X.LP
XGiven a makefile created by
X.I mkmf,
X.I make
Xrecognizes the following requests:
X.IP \fBall\fR 15
XCompile and load a program or library.
X.IP \fBclean\fR
XRemove all unnecessary files.
X.IP \fBdepend\fR
XEdit the makefile and regenerate the dependency information.
X.IP \fBextract\fR
XExtract all the object files from the library and place them in the
Xsame directory as the source code files. The library is not altered.
X.IP \fBindex\fR
XPrint an index of functions on standard output.
X.IP \fBinstall\fR
XCompile and load the program or library and move it to its destination
Xdirectory.
X.IP \fBlibrary\fR
XCompile and load a library.
X.IP \fBprint\fR
XPrint source code files on standard output.
X.IP \fBtags\fR
XCreate a tags file for the
X.I ex
Xeditor, for C, Pascal, and Fortran source code files.
X.IP \fBprogram\fR
XCompile and link a program.
X.IP \fBupdate\fR
XRecompile only if there are source code files that are newer than the
Xprogram or library, link and install the program or library. In the case
Xof an out-of-date library, all the object files are extracted from the
Xlibrary before any recompilation takes place.
X.LP
XSeveral requests may be given simultaneously. For example, to
Xcompile and link a program,
Xmove the program to its destination directory, and remove
Xany unnecessary object files:
X.IP
Xmake program install clean
X.LP
X\fBMacro Definitions\fR
X.LP
X.I Mkmf
Xunderstands the following macro definitions:
X.IP CFLAGS 15
XC compiler flags. After searching for included files in the directory
Xcurrently being processed,
X.I mkmf
Xsearchs in directories named in
X.B \-I
Xcompiler options, and then in the `/usr/include' directory.
XAlternatively, the include directories can be named directly
Xon the command line in the same syntax as they are expected by cc,
Xnamely, \fB\-Ifilename\fR.  Any number of include directories may be 
Xso named.
X.IP DEST
XDirectory where the program or library is to be installed.
X.IP EXTHDRS
XList of included files external to the current directory.
X.I Mkmf
Xautomatically updates this macro definition in the makefile if dependency
Xinformation is being generated.
X.IP FFLAGS
XFortran compiler flags. After searching for included files in the directory
Xcurrently being processed,
X.I mkmf
Xsearchs in directories named in
X.B \-I
Xcompiler options, and then in the `/usr/include' directory.
X.IP HDRS
XList of included files in the current directory.
X.I Mkmf
Xautomatically updates this macro definition in the makefile.
X.IP LIBRARY
XLibrary name. This macro also implies the
X.B \-l
Xoption.
X.IP LIBS
XList of libraries needed by the link editor to resolve external references.
X.IP MAKEFILE
XMakefile name.
X.IP OBJS
XList of object files.
X.I Mkmf
Xautomatically updates this macro definition in the makefile.
X.IP PROGRAM
XProgram name.
X.IP SRCS
XList of source code files.
X.I Mkmf
Xautomatically updates this macro definition in the makefile.
X.IP SUFFIX
XList of additional file name suffixes for
X.I mkmf
Xto know about.
X.LP
XBoth these and any other macro definitions already within the makefile may
Xbe replaced by definitions on the command line in the form
X.I "macroname=value".
XFor example, to change the C compiler flags, the program name, and the
Xdestination directory in the makefile, the user might type the following line:
X.LP
X.nf
X	mkmf  ``CFLAGS=\-I../include  \-O''  PROGRAM=mkmf  DEST=/usr/new
X.fi
X.LP
XNote that macro definitions like CFLAGS with blanks in them
Xmust be enclosed in double quote `"' marks.
X.LP
X\fBFile Name Suffixes\fR
X.LP
X.I Mkmf
Xcan be instructed to recognize additional file name suffixes, or ignore ones
Xthat it already knows about, by specifying suffix descriptions in
Xthe SUFFIX macro definition. Each suffix description takes the
Xform `.\fIsuffix:tI\^\fR' where
X.I t
Xis a character indicating the contents of the file (s = source file,
Xo = object file, h = header file, x = executable file) and
X.I I
Xis an optional character indicating the include syntax for included
Xfiles (C = C syntax, F = Fortran, Efl, and Ratfor syntax, P = Pascal
Xsyntax). The following table describes
Xthe default configuration for
X.I mkmf:
X
X.nf
X.ta 1.5i +1i
X	.c:sC	C
X	.e:sF	Efl
X	.F:sF	Fortran
X	.f:sF	Fortran
X	.h:h	Include files
X	.i:h	Pascal include files
X	.l:sC	Lex or Lisp
X	.o:o	Object files
X	.p:sP	Pascal
X	.r:sF	Ratfor
X	.s:s	Assembler
X	.y:sC	Yacc
X.fi
X.DT
X.LP
XFor example, to change the object file suffix to .obj, undefine the Pascal
Xinclude file suffix, and prevent Fortran files from being scanned for
Xincluded files, the SUFFIX macro definition might look like:
X.IP
X\&"SUFFIX = .obj:o  .i:  .f:s"
X.LP
X\fBInclude Statement Syntax\fR
X.LP
XThe syntax of include statements for C, Fortran, and Pascal source code are
Xof the form
X.IP \fB\C:\fR
X#include "\fIfilename\fR"
X.RS
Xwhere # must be the first character in the line.
X.RE
X.IP \fB\Fortran:\fR
Xinclude '\fIfilename\fR'
X.RS
XINCLUDE '\fIfilename\fR'
X.br
Xwhere the include statement starts in column 7.
X.RE
X.IP \fB\Pascal:\fR
X#include "\fIfilename\fR"
X.RS
X#INCLUDE "\fIfilename\fR"
X.br
Xwhere # must be the first character in the line.
X.RE
X.LP
X\fBUser-Defined Templates\fR
X.LP
XIf
X.I mkmf
Xcan not find a makefile within the current directory, it normally uses
Xone of the standard makefile templates, `p.Makefile' or `l.Makefile', in
X/usr/new/lib unless the user has alternative `p.Makefile'
Xor `l.Makefile' template files in a directory $PROJECT/lib where
X$PROJECT is the absolute pathname of the directory assigned to the PROJECT
Xenvironment variable.
X.SH OPTIONS
X.IP \fB\-a\fR
XWhen searching a directory for source and include files, also consider files
Xwhich have names beginning with periods.  By default, 
X.I mkmf
Xignores
Xfile names which have leading "dots," such as those of
Xbackup files created by some
Xeditors.
X.IP \fB\-c\fR
XSuppress `creating
X.I makefile
Xfrom ...' message.
X.IP \fB\-d\fR
XTurn
X.B off
Xscanning of source code for `include' files. Old dependency information
Xis left untouched in the makefile.
X.IP "\fB\-f \fImakefile\fR"
XSpecify an alternative
X.I makefile
Xfile name. The default file name is `Makefile'.
X.IP \fB\-i\fR
XCause
X.I mkmf
Xto prompt the user for the name of the program or library, and the
Xdirectory where it is to be installed. If a carriage return is typed
Xin response to each of these queries,
X.I mkmf
Xwill assume that the default program name is
X.I a.out
Xor the default library name is
X.I lib.a,
Xand the destination directory is the current directory.
X.IP \fB\-I\fIinclude\fR
XSpecify an additional directory to search for include files.
XThis option is in the same syntax as cc expects, namely, no
Xspace between the
X.B \-I
Xand the \fIinclude dir.\fR
X.IP \fB\-l\fR
XForce the makefile to be a library makefile.
X.IP "\fB\-F \fItemplate\fR"
XSpecify an alternative makefile
X.I template
Xfile name. The default program makefile template is `p.Makefile'
Xand the default library makefile template is `l.Makefile'.
X.I Mkmf
Xnormally looks for
X.I template 
Xin /usr/new/lib or $PROJECT/lib. However,
X.I template
Xcan be specified as an absolute pathname.
X.SH FILES
X.nf
X.ta \w'/usr/new/lib/p.Makefile'u+.5i
X/usr/new/lib/p.Makefile	Standard program makefile template.
X/usr/new/lib/l.Makefile	Standard library makefile template.
X$PROJECT/lib/p.Makefile	User-defined program makefile template.
X$PROJECT/lib/l.Makefile	User-defined library makefile template.
X.fi
X.DT
X.SH "SEE ALSO"
Xar(1), ctags(1), ex(1), ld(1), ls(1), make(1)
X.sp
XFeldman, S.I., "Make \- A Program for Maintaining Computer Programs"
X.sp
XWalden, K., "Automatic Generation of Make Dependencies", \fISoftware\-Practice
Xand Experience\fP, vol. 14, no. 6, pp. 575-585, June 1984.
X.SH DIAGNOSTICS
XExit status 0 is normal. Exit status 1 indicates an error.
X.SH AUTHOR
XPeter J. Nicklin
X.SH BUGS
XThe name of the makefile is included as a macro definition within the
Xmakefile and must be changed if the makefile is renamed.
X.LP
XSince executable files are dependent on libraries, standard library
Xabbreviations must be expanded to full pathnames within the LIBS macro
Xdefinition in the makefile.
X.LP
XGenerated dependency information appears after a line in the makefile
Xbeginning with `###'. This line must
X.B not
Xbe removed, nor must any other information be inserted in the makefile
Xbelow this line.
@\End\of\File\
else
  echo "shar: Will not over write man/mann/mkmf.n"
fi
if `test ! -s man/mann/Makefile`
then
echo "x - man/mann/Makefile"
sed 's/^X//' > man/mann/Makefile << '@\End\of\File\'
X#DEST	      = $(DESTDIR)/usr/new/man/mann
XDEST	      = $(DESTDIR)/man/mann
X
XMAKEFILE      = Makefile
X
XPRINT	      = vtroff -man
X
XSRCS	      = mkmf.n
X
XSUFFIX	      = .n:s
X
XVERSION	      = V4BSD
X
Xall:;
X
Xclean:;
X
Xco:;
X
Xdepend:;
X
Xdiff:;
X
Xindex:;
X
Xinstall:;	@echo Installing $(SRCS) in $(DEST)
X		@install -o jwm -g src -m 644 -c $(SRCS) $(DEST)
X		@ls -lg $(DEST)/$(SRCS)
X
Xlint:;
X
Xprint:		$(SRCS)
X		@$(PRINT) $?
X		@touch print
X
Xtags:;
X
Xupdate:		$(SRCS)
X		@echo Installing $? in $(DEST)
X		@cp $? $(DEST)
X###
@\End\of\File\
else
  echo "shar: Will not over write man/mann/Makefile"
fi
if `test ! -d src`
then
  mkdir src
  echo "mkdir src"
fi
if `test ! -s src/Makefile`
then
echo "x - src/Makefile"
sed 's/^X//' > src/Makefile << '@\End\of\File\'
XPROGRAM	      = mkmf
X
X#DEST	      = /usr/new/bin
XDEST	      = $(DESTDIR)/bin
X
XSRCDEST	      = src/mkmf/src
X
XMANDIR	      = /usr/new/man/man1
X
XMANUAL	      =
X
XHOMEDIR	      = $(HOME)
X
X#CFLAGS	      = -g -D$(VERSION)
XCFLAGS	      = -O -D$(VERSION) -DORIGINAL
X
XVERSION	      = V4BSD
X
XLIBS	      =
X
X#IFLAGS	      = -g src -o jwm -c
XIFLAGS	      = -g src -o ljz -c
X
XYFLAGS	      = -d
X
XLFLAGS	      =
X
XLDFLAGS	      = $(CFLAGS)
X
XLINKER	      = cc
X
XMAKEFILE      = Makefile
X
XEXTHDRS	      =
X
XHDRS	      = Mkmf.h \
X		defaultrul.h \
X		defaultsfx.h \
X		dlist.h \
X		getarg.h \
X		hash.h \
X		macro.h \
X		null.h \
X		path.h \
X		rule.h \
X		sccsid.h \
X		slist.h \
X		spms.h \
X		suffix.h \
X		system.h \
X		target.h \
X		yesno.h
X
XOBJS	      = Mkmf.o \
X		badopt.o \
X		buildlist.o \
X		depend.o \
X		dlist.o \
X		editmf.o \
X		getcwp.o \
X		getproject.o \
X		hash.o \
X		iolin.o \
X		macro.o \
X		misc.o \
X		mustfopen.o \
X		optpath.o \
X		pathcat.o \
X		pathhead.o \
X		pperror.o \
X		rule.o \
X		slappend.o \
X		slinit.o \
X		slsort.o \
X		strpcpy.o \
X		strsav.o \
X		suffix.o \
X		usage.o \
X		warn.o \
X		warn2.o \
X		warns.o
X
XSRCS	      = Mkmf.c \
X		badopt.c \
X		buildlist.c \
X		depend.c \
X		dlist.c \
X		editmf.c \
X		getcwp.c \
X		getproject.c \
X		hash.c \
X		iolin.c \
X		macro.c \
X		misc.c \
X		mustfopen.c \
X		optpath.c \
X		pathcat.c \
X		pathhead.c \
X		pperror.c \
X		rule.c \
X		slappend.c \
X		slinit.c \
X		slsort.c \
X		strpcpy.c \
X		strsav.c \
X		suffix.c \
X		usage.c \
X		warn.c \
X		warn2.c \
X		warns.c
X
XDISTRIB	      = $(MAKEFILE) $(SRCS) $(HDRS) $(EXTHDRS) $(MANUAL)
X
XWORKINGSET    = $(DISTRIB)
X
XSHAR	      = $(PROGRAM).shar
X
X$(PROGRAM):     $(OBJS)
X		@rm -f $(PROGRAM) core
X		@echo "Linking \`$(PROGRAM)' ..."
X		@$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
X
Xinstall:	$(DEST)/$(PROGRAM) $(MANDIR)/$(MANUAL)
X		@echo "Installation completed."
X
Xclean:;		@rm -f $(OBJS) $(PROGRAM) core *.out .#*
X
Xdepend:;	@rm -f .#*
X		@mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) \
X		'DEST=$$(HOMEDIR)/bin' \
X		HOMEDIR=`echo $$HOME`
X
Xshar::		$(SHAR)
X
X$(SHAR):	$(DISTRIB)
X		@rm -f $(SHAR)
X		shar $(SHAR) $(DISTRIB)
X		@ls -lgs $(SHAR)
X
Xtags:		$(HDRS) $(SRCS)
X		@ctags $(HDRS) $(SRCS)
X
Xmanual:		$(MANDIR)/$(MANUAL)
X
Xlcount:;	@cstat -s $(HDRS) $(SRCS) $(MAKEFILE)
X
Xsrclist:;	@echo $(DISTRIB) > srclist
X
Xbackup:		renoir
X
Xrenoir:;	@rdist -cyw $(WORKINGSET) $@:$(SRCDEST)
X
Xdougfir:;	@rdist -cyw $(WORKINGSET) $@:$(SRCDEST)
X
Xeros:;		@rdist -cyw $(WORKINGSET) $@:/usr/tmp/jwm/$(SRCDEST)
X
Xfir:;		@rdist -cyw $(WORKINGSET) $@:/fir/jwm/$(SRCDEST)
X
X$(DEST)/$(PROGRAM): $(PROGRAM)
X		@install $(IFLAGS) -s -m 0775 $(PROGRAM) $(DEST)
X		@ls -lg $(DEST)/$(PROGRAM)
X
X$(MANDIR)/$(MANUAL): $(MANUAL)
X		install $(IFLAGS) -m 0644 $(MANUAL) $(MANDIR)
X		@ls -lgs $(MANDIR)/$(MANUAL)
X###
XMkmf.o: sccsid.h Mkmf.h getarg.h hash.h null.h path.h target.h slist.h \
X	suffix.h system.h yesno.h defaultrul.h defaultsfx.h
Xbadopt.o: null.h
Xbuildlist.o: Mkmf.h hash.h null.h path.h slist.h suffix.h system.h yesno.h
Xdepend.o: Mkmf.h dlist.h hash.h macro.h null.h path.h slist.h system.h \
X	yesno.h
Xdlist.o: Mkmf.h dlist.h hash.h null.h slist.h yesno.h
Xeditmf.o: Mkmf.h dlist.h hash.h macro.h null.h slist.h system.h yesno.h
Xgetcwp.o: null.h
Xgetproject.o: null.h
Xhash.o: null.h hash.h macro.h
Xiolin.o: yesno.h
Xmacro.o: Mkmf.h hash.h macro.h null.h slist.h yesno.h
Xmisc.o: Mkmf.h hash.h macro.h null.h path.h target.h spms.h suffix.h \
X	system.h yesno.h
Xoptpath.o: path.h
Xpathcat.o: path.h
Xpathhead.o: null.h path.h
Xrule.o: Mkmf.h null.h rule.h slist.h suffix.h system.h yesno.h
Xslappend.o: macro.h null.h slist.h
Xslinit.o: null.h slist.h
Xslsort.o: null.h slist.h yesno.h
Xstrsav.o: null.h
Xsuffix.o: Mkmf.h hash.h macro.h null.h suffix.h yesno.h
Xusage.o: null.h
Xwarn.o: null.h
Xwarn2.o: null.h
Xwarns.o: null.h
@\End\of\File\
else
  echo "shar: Will not over write src/Makefile"
fi
if `test ! -s src/Mkmf.c`
then
echo "x - src/Mkmf.c"
sed 's/^X//' > src/Mkmf.c << '@\End\of\File\'
Xstatic char *rcsid = "$Header: Mkmf.c,v 1.7 86/01/12 00:48:26 lepreau Exp $";
X#include "sccsid.h"
X/*
X * mkmf - makefile editor
X *
X * Author: Peter J. Nicklin
X */
X#include "Mkmf.h"
X#include "getarg.h"
X#include "hash.h"
X#include "null.h"
X#include "path.h"
X#include "target.h"
X#include "slist.h"
X#include "suffix.h"
X#include "system.h"
X#include "yesno.h"
X
Xchar *L_MAKEFILE = "l.Makefile";	/* default library makefile template */
Xchar OBJSFX[SUFFIXSIZE] = ".o";		/* default object suffix */
Xchar *P_MAKEFILE = "p.Makefile";	/* default program makefile template */
Xchar *PGN = "mkmf";			/* program name */
Xchar idir[8096];			/* additional include directories. */
Xint dashI = 0;				/* do additional inc. dirs? */
Xint CFLAG = YES;			/* makefile creation message flag */
Xint AFLAG = NO;				/* accept src files w/ leading dots? */
Xint DEPEND = 1;				/* dependency analysis? */
XSLIST *HEADLIST;			/* header file name list */
XSLIST *LIBLIST;				/* library pathname list */
XSLIST *SRCLIST;				/* source file name list */
XHASH *MDEFTABLE;			/* macro definition table */
X
Xchar *DEFRULE[] =			/* default preprocessor rules */
X	{
X#include "defaultrul.h"
X	NULL
X	};
X
XSUFFIX DEFSFX[] =			/* default suffix list */
X	{
X#include "defaultsfx.h"
X	NULL, 0
X	};
X
Xmain(argc, argv)
X	int argc;
X	char **argv;
X{
X	char *mfname = NULL;		/* makefile name */
X	char mfpath[PATHSIZE];		/* makefile template pathname */
X	HASHBLK *htb;			/* hash table block */
X	HASHBLK *htinstall();		/* install hash table entry */
X	HASHBLK *htlookup();		/* find hash table entry */
X	int buildliblist();		/* build list of library pathnames */
X	int buildruletable();		/* build table of preprocessor rules */
X	int buildsfxtable();		/* build table of suffixes */
X	int buildsrclist();		/* build list of source file names */
X	int findmf();			/* find makefile */
X	int status = 0;			/* exit status */
X	int storemacro();		/* store macro definition */
X	short iflag = NO;		/* interactive flag */
X	TARGET target;			/* type of makefile target */
X	void answer();			/* install answer in macro def table */
X	void editmf();			/* edit makefile */
X
X	target.type = target.dest = VUNKNOWN;
X
X	{
X	register char *s;		/* option pointer */
X	while (--argc > 0 && **++argv == '-')
X		{
X		for (s = argv[0]+1; *s != '\0'; s++)
X			switch (*s)
X				{
X				case 'F':
X					P_MAKEFILE = L_MAKEFILE = GETARG(s);
X					if (P_MAKEFILE==NULL || *P_MAKEFILE=='\0')
X						{
X						warn("missing template name");
X						status = 1;
X						}
X					goto endfor;
X				case 'I':
X					/* check for an argument. */
X					if (*(s + 1) == '\0') {
X						warn("null include directory to -I");
X						status = 1;
X					} else if (dashI) {
X						strcat(idir, " ");
X						strcat(idir, argv[0]);
X					} else {
X						dashI = 1;
X						strcpy(idir, argv[0]);
X					}
X					goto endfor;
X				case 'a':
X					AFLAG = YES;
X					break;
X				case 'c':
X					CFLAG = NO;
X					break;
X				case 'd':
X					/* turn OFF dependency analysis */
X					DEPEND = 0;
X					break;
X				case 'f':
X					mfname = GETARG(s);
X					if (mfname == NULL || *mfname == '\0')
X						{
X						warn("missing makefile name");
X						status = 1;
X						}
X					goto endfor;
X				case 'i':
X					iflag = YES;
X					break;
X				case 'l':
X					target.type = VLIBRARY;
X					break;
X				default:
X					badopt(**argv, *s);
X					status = 1;
X					goto endfor;
X				}
X		endfor: continue;
X		}
X	}
X	
X	/* initialize macro definition table */
X	MDEFTABLE = htinit(MDEFTABLESIZE);
X
X	/* get command line macro definitions */
X	for (; argc > 0; argc--, argv++)
X		if (storemacro(*argv) == NO)
X			{
X			warns("%s not a macro definition", *argv);
X			status = 1;
X			}
X
X	/* add the additional include dirs, if extant. */
X	if (dashI && htinstall(MMOREINCDIRS, idir, VREADONLY, MDEFTABLE) == NULL)
X		status = 1;
X
X	if (status == 1)
X		{
X		usage("[-cdil] [-f makefile] [-F template] [-Iinclude dir] [macroname=value...]");
X		exit(1);
X		}
X
X
X	/* determine the makefile name */
X	if (mfname == NULL)
X		if ((htb = htlookup(MMAKEFILE, MDEFTABLE)) != NULL)
X			mfname = htb->h_def;
X		else if (FILEXIST("makefile"))
X			mfname = "makefile";
X		else if (FILEXIST("Makefile"))
X			mfname = "Makefile";
X		else
X			mfname = "Makefile";
X	if (htinstall(MMAKEFILE, mfname, VREADWRITE, MDEFTABLE) == NULL)
X		exit(1);
X
X
X	/* find the makefile (template) and load useful macro definitions */
X	if (target.type == VUNKNOWN)
X		{
X		if (htlookup(MPROGRAM, MDEFTABLE) != NULL)
X			target.type = VPROGRAM;
X		else if (htlookup(MLIBRARY, MDEFTABLE) != NULL)
X			target.type = VLIBRARY;
X		}
X	if (findmf(mfname, mfpath, &target) == NO)
X		exit(1);
X	
X
X	/* interactive option */
X	if (iflag == YES)
X		{
X		if (htlookup(MPROGRAM, MDEFTABLE) == NULL &&
X		    htlookup(MLIBRARY, MDEFTABLE) == NULL)
X			if (target.type == VPROGRAM)
X				{
X				printf("program name? ");
X				answer(MPROGRAM, VREADWRITE);
X				}
X			else if (target.type == VLIBRARY)
X				{
X				printf("library name? ");
X				answer(MLIBRARY, VREADWRITE);
X				}
X		if (htlookup(MDESTDIR, MDEFTABLE) == NULL && target.dest == VDESTDIR)
X			{
X			printf("destination directory? ");
X			answer(MDESTDIR, VREADWRITE);
X			}
X		}
X
X	/* build the suffix table */
X	if (buildsfxtable() == NO)
X		exit(1);
X
X	/* build the rule table */
X	if (buildruletable() == NO)
X		exit(1);
X
X	/* build the source code and header file name lists */
X	if (buildsrclist() == NO)
X		exit(1);
X	
X
X	/* build the library pathname list */
X	if (buildliblist() == NO)
X		exit(1);
X
X
X	/* edit makefile */
X	editmf(mfname, mfpath);
X
X	exit(0);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/Mkmf.c"
fi
if `test ! -s src/badopt.c`
then
echo "x - src/badopt.c"
sed 's/^X//' > src/badopt.c << '@\End\of\File\'
X/* $Header: badopt.c,v 1.2 85/04/02 07:45:43 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * badopt() places a "bad option" error message on the standard error
X * output stream stderr.
X */
X#include <stdio.h>
X#include "null.h"
X
Xextern char *PGN;			/* program name */
X
Xbadopt(sign, c)
X	char c;				/* offending option */
X	char sign;			/* '+' or '-' sign preceding option */
X{
X	if (PGN != NULL && *PGN != '\0')
X		fprintf(stderr, "%s: ", PGN);
X	fprintf(stderr, "bad option %c%c\n", sign, c);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/badopt.c"
fi
if `test ! -s src/buildlist.c`
then
echo "x - src/buildlist.c"
sed 's/^X//' > src/buildlist.c << '@\End\of\File\'
X/* $Header: buildlist.c,v 1.3 86/01/12 00:49:30 lepreau Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <sys/types.h>
X#include <sys/dir.h>
X#include <stdio.h>
X#include <ctype.h>
X#include "Mkmf.h"
X#include "hash.h"
X#include "null.h"
X#include "path.h"
X#include "slist.h"
X#include "suffix.h"
X#include "system.h"
X#include "yesno.h"
X
X/*
X * buftolist() copies the items from a buffer to a singly-linked list.
X * Returns integer YES if successful, otherwise NO.
X */
Xbuftolist(buf, list)
X	char *buf;			/* item buffer */
X	SLIST *list;			/* receiving list */
X{
X	char *gettoken();		/* get next token */
X	char *slappend();		/* append file name to list */
X	char token[MAXNAMLEN];		/* item buffer */
X
X	while ((buf = gettoken(token, buf)) != NULL)
X		{
X		if (slappend(token, list) == NULL)
X			return(NO);
X		}
X	return(YES);
X}
X
X
X
X/*
X * buildliblist() reads library pathnames from the LIBLIST macro
X * definition, and adds them to the library pathname list. Libraries
X * may be specified as `-lx'. Returns integer YES if successful,
X * otherwise NO.
X */
Xbuildliblist()
X{
X	extern SLIST *LIBLIST;		/* library pathname list */
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	HASHBLK *htb;			/* hash table block */
X	HASHBLK *htlookup();		/* find hash table entry */
X	int libbuftolist();		/* load library pathnames into list */
X	SLIST *slinit();		/* initialize singly-linked list */
X	void htrm();			/* remove hash table entry */
X
X	LIBLIST = NULL;
X	if ((htb = htlookup(MLIBLIST, MDEFTABLE)) != NULL)
X		{
X		LIBLIST = slinit();
X		if (libbuftolist(htb->h_def, LIBLIST) == NO)
X			return(NO);
X		}
X	htrm(MLIBLIST, MDEFTABLE);
X	return(YES);
X}
X
X
X
X/*
X * buildsrclist() takes source and header file names from command line
X * macro definitions or the current directory and appends them to source
X * or header file name lists as appropriate. Returns integer YES if
X * if successful, otherwise NO.
X */
Xbuildsrclist()
X{
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	extern SLIST *HEADLIST;		/* header file name list */
X	extern SLIST *SRCLIST;		/* source file name list */
X	char *slappend();		/* append file name to list */
X	HASHBLK *headhtb;		/* HEADERS macro hash table block */
X	HASHBLK *htlookup();		/* find hash table entry */
X	HASHBLK *srchtb;		/* SOURCE macro hash table block */
X	int buftolist();		/* copy items from buffer to list */
X	int needheaders = 1;		/* need header file names */
X	int needsource = 1;		/* need source file names */
X	int read_dir();			/* read dir for source and headers */
X	int slsort();			/* sort singly-linked list */
X	int strcmp();			/* string comparison */
X	SLIST *slinit();		/* initialize singly-linked list */
X
X	HEADLIST = slinit();
X	SRCLIST = slinit();
X
X	/* build lists from command line macro definitions */
X	if ((headhtb = htlookup(MHEADERS, MDEFTABLE)) != NULL)
X		{
X		if (buftolist(headhtb->h_def, HEADLIST) == NO)
X			return(NO);
X		needheaders--;
X		}
X	if ((srchtb = htlookup(MSOURCE, MDEFTABLE)) != NULL)
X		{
X		if (buftolist(srchtb->h_def, SRCLIST) == NO)
X			return(NO);
X		needsource--;
X		}
X	
X	/* read the current directory to get source and header file names */
X	if (needheaders || needsource)
X		if (read_dir(needheaders, needsource) == NO)
X			return(NO);
X
X	if (slsort(strcmp, SRCLIST) == NO)
X		return(NO);
X	if (slsort(strcmp, HEADLIST) == NO)
X		return(NO);
X	return(YES);
X}
X
X
X
X/*
X * expandlibpath() converts a library file specified by `-lx' into a full
X * pathname. /lib and /usr/lib are searched for the library in the form
X * libx.a. An integer YES is returned if the library was found, otherwise NO.
X * A library file which doesn't begin with `-' is left unchanged.
X */
Xexpandlibpath(libpath)
X	char *libpath;			/* library pathname buffer */
X{
X	char *lib;			/* /lib library pathname template */
X	char *strcpy();			/* string copy */
X	char *usrlib;			/* /usr/lib library pathname template */
X	int i;				/* library pathname index */
X
X#ifndef ORIGINAL
X	return (YES);
X#endif !ORIGINAL
X
X	lib = "/lib/libxxxxxxxxxxxxxxxxxxxxxxxxx";
X	usrlib = "/usr/lib/libxxxxxxxxxxxxxxxxxxxxxxxxx";
X
X	if (libpath[0] == '-' && libpath[1] == 'l')
X		{
X		for (i = 0; libpath[i+2] != '\0' && i < 22; i++)
X			{
X			lib[i+8] = libpath[i+2];
X			usrlib[i+12] = libpath[i+2];
X			}
X		lib[i+8] = usrlib[i+12] = '.';
X		lib[i+9] = usrlib[i+13] = 'a';
X		lib[i+10] = usrlib[i+14] = '\0';
X		if (FILEXIST(lib))
X			{
X			strcpy(libpath, lib);
X			return(YES);
X			}
X		else if (FILEXIST(usrlib))
X			{
X			strcpy(libpath, usrlib);
X			return(YES);
X			}
X		else
X			return(NO);
X		}
X	return(YES);
X}
X
X
X
X/*
X * libbuftolist() appends each library pathname specified in libbuf to
X * the liblist library pathname list.
X */
Xlibbuftolist(libbuf, liblist)
X	char *libbuf;			/* library pathname buffer */
X	SLIST *liblist;			/* library pathname list */
X{
X	char *gettoken();		/* get next token */
X	char libpath[PATHSIZE];		/* library file pathname */
X	char *slappend();		/* append file name to list */
X	int expandlibpath();		/* -lx -> full library pathname */
X
X	while ((libbuf = gettoken(libpath, libbuf)) != NULL)
X		{
X		if (expandlibpath(libpath) == NO)
X			{
X			warns("can't find library %s", libpath);
X			return(NO);
X			}
X		if (slappend(libpath, liblist) == NULL)
X			return(NO);
X		}
X	return(YES);
X}
X
X
X
X/*
X * read_dir() reads filenames from the current directory and adds them
X * to the source or header file name lists as appropriate. Returns
X * integer YES if successful, otherwise NO.
X */
Xread_dir(needheaders, needsource)
X	int needheaders;		/* need header file names */
X	int needsource;			/* need source file names */
X{
X	extern int AFLAG;		/* accept src files w/ leading dots? */
X	extern SLIST *HEADLIST;		/* header file name list */
X	extern SLIST *SRCLIST;		/* source file name list */
X	char *rindex();			/* find last occurrence of character */
X	char *slappend();		/* append file name to list */
X	char *suffix;			/* pointer to file name suffix */
X	char *p;			/* beginning of file name component */
X	DIR *dirp;			/* directory stream */
X	DIR *opendir();			/* open directory stream */
X	int lookupsfx();		/* get suffix type */
X	int sfxtyp;			/* type of suffix */
X	struct direct *dp;		/* directory entry pointer */
X	struct direct *readdir();	/* read a directory entry */
X
X	if ((dirp = opendir(CURDIR)) == NULL)
X		{
X		warn("can't open current directory");
X		return(NO);
X		}
X	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
X		if ((suffix = rindex(dp->d_name, '.')) != NULL)
X			{
X			if ((p = rindex(dp->d_name, '/')) != NULL)
X				p++;
X			else
X				p = dp->d_name;
X			if (*p == '.' && (AFLAG == 0))
X				continue;
X			suffix++;
X			sfxtyp = lookupsfx(suffix);
X			if (sfxtyp == SFXSRC)
X				{
X				if (needsource)
X					if (slappend(dp->d_name, SRCLIST) == NULL)
X						return(NO);
X				}
X			else if (sfxtyp == SFXHEAD)
X				{
X				if (needheaders)
X					if (slappend(dp->d_name, HEADLIST) == NULL)
X						return(NO);
X				}
X			}
X	closedir(dirp);
X	return(YES);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/buildlist.c"
fi
if `test ! -s src/depend.c`
then
echo "x - src/depend.c"
sed 's/^X//' > src/depend.c << '@\End\of\File\'
X/* $Header: depend.c,v 1.14 86/05/15 09:01:04 lepreau Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <ctype.h>
X#include <stdio.h>
X#include "Mkmf.h"
X#include "dlist.h"
X#include "hash.h"
X#include "macro.h"
X#include "null.h"
X#include "path.h"
X#include "slist.h"
X#include "system.h"
X#include "yesno.h"
X
X#define USRINCLUDE		"/usr/include/"
X#define CURINCLUDE		"./"
X#define TOLOWER(c)		(isupper(c) ? tolower(c) : (c))
X#define SKIPWHITESPACE(c, f) while ((c = getc(f))==' ' || c=='\t'); ungetc(c,f);
X
X/*
X * Include file state
X */
X#define NOTFOUND		0	/* not found anywhere */
X#define EXTERNAL		1	/* not found in current directory */
X#define INTERNAL		2	/* found in current directory */
X#define FROMRULE		3	/* derived from tranformation rule */
X
X/*
X * Include files are stored in hash tables by direct chaining (See
X * p. 134 in `The C Programming Language' by Kernighan and Ritchie).
X * Included include files are also added to a singly-linked list
X * attached to the hash table entry for the include file.
X */
Xstatic HASH *C_INCLUDETABLE = NULL;	/* C include file hash table */
Xstatic HASH *F_INCLUDETABLE = NULL;	/* Fortran include file hash table */
Xstatic HASH *P_INCLUDETABLE = NULL;	/* Pascal include file hash table */
X/*
X * Additional include directories are specified via the -I compiler
X * command line option. These directories are stored in singly-linked lists.
X * We also assume that the last look-up directory is "/usr/include".
X */
Xstatic SLIST *C_INCDIR;			/* C include directories */
Xstatic SLIST *F_INCDIR;			/* Fortran include directories */
Xstatic SLIST *P_INCDIR;			/* Pascal include directories */
X
XSLIST *EXTLIST;				/* external header file name list */
X
Xextern char *PGN;			/* program name */
X
X/*
X * addincdir() adds directories containing include files to the
X * appropriate singly-linked list. The pathnames to the directories
X * are derived from makefile macro definitions.
X */
Xvoid
Xaddincdir()
X{
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	char *slappend();		/* append to singly-linked list */
X	HASHBLK *htb;			/* hash table entry block */
X	HASHBLK *htlookup();		/* find hash table entry */
X	int cleanup();			/* remove temporary makefile and exit */
X	void getI();			/* get include directory pathnames */
X	extern int dashI;		/* include directories to scan */
X
X	/* C files */
X	if ((htb = htlookup(MCFLAGS, MDEFTABLE)) != NULL)
X		getI(htb->h_key, htb->h_def, C_INCDIR);
X	if (slappend(USRINCLUDE, C_INCDIR) == NULL)
X		cleanup();
X
X	/* add any directories specified via the mkmf -I flag. */
X	if (dashI) {
X		if ((htb = htlookup(MMOREINCDIRS, MDEFTABLE)) != NULL)
X			getI(htb->h_key, htb->h_def, C_INCDIR);
X		if (slappend(USRINCLUDE, C_INCDIR) == NULL)
X			cleanup();
X	}
X	
X	/* Fortran files */
X	if ((htb = htlookup(MFFLAGS, MDEFTABLE)) != NULL)
X		getI(htb->h_key, htb->h_def, F_INCDIR);
X	if (slappend(USRINCLUDE, F_INCDIR) == NULL)
X		cleanup();
X
X	/* Pascal files */
X	if ((htb = htlookup(MPFLAGS, MDEFTABLE)) != NULL)
X		getI(htb->h_key, htb->h_def, P_INCDIR);
X	if (slappend(USRINCLUDE, P_INCDIR) == NULL)
X		cleanup();
X}
X
X
X
X/*
X * findinclude() tries to find the pathname of an include file. Returns
X * integer INTERNAL if found in the current directory, EXTERNAL if found
X * somewhere else, FROMRULE if derived from a transformation rule,
X * otherwise NOTFOUND. The pathname is copied into incpath.
X */
X#define LOCALDIR(f)    (index(f, _PSC) == NULL)
X#define INCLUDETYPE(f) ((index(f, _PSC) == NULL) ? INTERNAL : EXTERNAL)
X
Xfindinclude(incpath, incname, lastname, type)
X	char *incpath;			/* pathname receiving buffer */
X	register char *incname;		/* include file name */
X	char *lastname;			/* file that includes incname */
X	int type;			/* file type */
X{
X	register char *pp;		/* include file path pointer */
X	char *index();			/* find occurrence of character */
X	char *optpath();		/* optimize pathname */
X	char *pathcat();		/* pathname concatenation */
X	char *pathhead();		/* remove pathname tail */
X	char *strcpy();			/* string copy */
X	char *strpcpy();		/* string copy and update pointer */
X	int lookuprule();		/* look up transformation rules */
X	SLBLK *slb;			/* singly-linked list block */
X	SLIST *slist;			/* include directory list pointer */
X
X	/*
X	 * look in /usr/include only
X	 */
X	if (*incname == '<')
X		{
X		pp = strpcpy(incpath, USRINCLUDE);
X		for (incname++; *incname != '>'; incname++, pp++)
X			*pp = *incname;
X		*pp = '\0';
X		return(FILEXIST(incpath) ? EXTERNAL : NOTFOUND);
X		}
X
X	/*
X	 * look for an absolute include file name
X	 */
X	if (*incname == '/')
X		{
X		strcpy(incpath, incname);
X		return(FILEXIST(incpath) ? EXTERNAL : NOTFOUND);
X		}
X
X	/*
X	 * look in current include directory to see if the file exists,
X	 * or can be generated by a transformation rule in the current
X	 * working directory.
X	 */
X	if (LOCALDIR(lastname))
X		{
X		if (LOCALDIR(incname))
X			{
X			if (lookuprule(incname, incpath) == YES)
X				return(FROMRULE);
X			}
X		strcpy(incpath, incname);
X		if (FILEXIST(incpath))
X			return(INCLUDETYPE(incpath));
X		}
X	else	{
X		strcpy(incpath, lastname);
X		pathcat(incpath, pathhead(incpath), incname);
X		optpath(incpath);
X		if (FILEXIST(incpath))
X			return(INCLUDETYPE(incpath));
X		}
X
X	/*
X	 * search directory list
X	 */
X	switch (type)
X		{
X		case INCLUDE_C:
X			slist = C_INCDIR;
X			break;
X		case INCLUDE_FORTRAN:
X			slist = F_INCDIR;
X			break;
X		case INCLUDE_PASCAL:
X			slist = P_INCDIR;
X			break;
X		}
X	for (slb = slist->head; slb != NULL; slb = slb->next)
X		{
X		pp = strpcpy(incpath, slb->key);
X		strcpy(pp, incname);
X		optpath(incpath);
X		if (FILEXIST(incpath))
X			return(INCLUDETYPE(incpath));
X		}
X	return(NOTFOUND);
X}
X
X
X
X/*
X * getI() appends include directories found via the -I compiler option to
X * a singly linked list.
X */
Xvoid
XgetI(mnam, mdef, slist)
X	char *mnam;			/* compiler options macro name */
X	char *mdef;			/* compiler options macro definition */
X	SLIST *slist;			/* singly-linked list */
X{
X	char *gettoken();		/* get next token */
X	char incpath[PATHSIZE];		/* include directory pathname buffer */
X	char *slappend();		/* append to singly-linked list */
X	char *strcat();			/* string concatenation */
X	int cleanup();			/* remove temporary makefile and exit */
X
X	while ((mdef = gettoken(incpath, mdef)) != NULL)
X		if (incpath[0] == '-' && incpath[1] == 'I')
X			if (incpath[2] == '\0')	/* -I dir option */
X				{
X				if ((mdef = gettoken(incpath, mdef)) != NULL)
X					{
X					strcat(incpath, PATHSEP);
X					if (slappend(incpath, slist) == NULL)
X						cleanup();
X					}
X				else	{
X					warn2("missing include directory in %s %s",
X					       mnam, "macro definition");
X					break;
X					}
X				}
X			else	{		/* -Idir option */
X				strcat(incpath+2, PATHSEP);
X				if (slappend(incpath+2, slist) == NULL)
X					cleanup();
X				}
X}
X
X
X
X/*
X * getinclude() fetchs an include file name from a line of source code.
X * /usr/include '<' and '>' delimiters remain with the filename to
X * distinguish it from an include file in a local directory. Returns
X * NO if syntax error, otherwise YES.
X */
Xgetinclude(incname, curname, lineno, ifp)
X	char *curname;			/* current file name */
X	char *incname;			/* include file name receiving buffer */
X	int lineno;			/* current line number */
X	register FILE *ifp;		/* input stream */
X{
X	register char *ip;		/* include file name buffer pointer */
X	register int c;			/* current character */
X
X	SKIPWHITESPACE(c, ifp);
X	for (ip = incname; (c = getc(ifp)) != EOF; ip++)
X		{
X		*ip = c;
X		if (c == '\n' || c == '\t' || c == ' ' || c == ';'  || c == ',')
X			{
X			ungetc(c, ifp);
X			break;
X			}
X		}
X	*ip = '\0';
X
X#ifndef ORIGINAL
X	if (*incname == '<' && ip[-1] == '>')
X		return (NO);
X#endif !ORIGINAL
X	if ((*incname == '<'  && ip[-1] != '>')  ||
X	    (*incname == '\"' && ip[-1] != '\"') ||
X	    (*incname == '\'' && ip[-1] != '\'') ||
X	    (*incname == '('  && ip[-1] != ')'))
X		{
X		fprintf(stderr,
X			"%s: \"%s\", line %d: bad include syntax for %s\n",
X			PGN, curname, lineno, incname);
X		return(NO);
X		}
X	if (*incname == '\"' || *incname == '\'' || *incname == '(')
X		{
X		ip[-1] = '\0';
X		ip = incname + 1;
X		while (*incname++ = *ip++)
X			continue;
X		}
X	return(YES);
X}
X
X
X
X/*
X * inclink() stores a pointer to a hash table block (which contains
X * include file information) somewhere. Returns a pointer to the somewhere,
X * or calls cleanup() if out of memory.
X */
XINCBLK *
Xinclink(htb)
X	HASHBLK *htb;			/* hash table block pointer to save */
X{
X	char *malloc();			/* memory allocator */
X	INCBLK *iblk;			/* pointer to new include chain block */
X	int cleanup();			/* remove temporary makefile and exit */
X
X	if ((iblk = (INCBLK *) malloc(sizeof(INCBLK))) == NULL)
X		{
X		warn("out of memory");
X		cleanup();
X		}
X	iblk->i_loop = NO;
X	iblk->i_hblk = htb;
X	iblk->i_next = NULL;
X	return(iblk);
X}
X
X
X
X/*
X * instalinclude() adds an include file name to the appropriate include
X * file hash table. Returns a pointer to the hash table block, or calls
X * cleanup() if out of memory.
X */
XHASHBLK *
Xinstalinclude(incname, incpath, type)
X	char *incname;			/* name of include file */
X	char *incpath;			/* path to include file */
X	int type;			/* type of source file */
X{
X	HASH *htinit();			/* initialize hash table */
X	HASHBLK *htb = NULL;		/* hash table block */
X	HASHBLK *htinstall();		/* install hash table entry */
X	int cleanup();			/* remove temporary makefile and exit */
X	int ilen;			/* include path length */
X	int strlen();			/* string length */
X
X	ilen = strlen(incpath);
X	switch (type)
X		{
X		case INCLUDE_C:
X			if (C_INCLUDETABLE == NULL)
X				{
X				C_INCLUDETABLE = htinit(INCLUDETABLESIZE);
X				}
X			htb = htinstall(incname, incpath, ilen, C_INCLUDETABLE);
X			break;
X		case INCLUDE_FORTRAN:
X			if (F_INCLUDETABLE == NULL)
X				{
X				F_INCLUDETABLE = htinit(INCLUDETABLESIZE);
X				}
X			htb = htinstall(incname, incpath, ilen, F_INCLUDETABLE);
X			break;
X		case INCLUDE_PASCAL:
X			if (P_INCLUDETABLE == NULL)
X				{
X				P_INCLUDETABLE = htinit(INCLUDETABLESIZE);
X				}
X			htb = htinstall(incname, incpath, ilen, P_INCLUDETABLE);
X			break;
X		}
X	if (htb == NULL)
X		cleanup();
X	return(htb);
X}
X
X
X
X/*
X * lookupinclude() returns a pointer to an include hash table block
X * corresponding to incname and type. Returns null if not found.
X */
XHASHBLK *
Xlookupinclude(incname, type)
X	char *incname;			/* name of include file */
X	int type;			/* type of source file */
X{
X	HASH *includetable = NULL;	/* include file hash table */
X	HASHBLK *htlookup();		/* find hash table entry */
X
X	switch (type)
X		{
X		case INCLUDE_C:
X			includetable = C_INCLUDETABLE;
X			break;
X		case INCLUDE_FORTRAN:
X			includetable = F_INCLUDETABLE;
X			break;
X		case INCLUDE_PASCAL:
X			includetable = P_INCLUDETABLE;
X			break;
X		}
X	return((includetable == NULL) ? NULL : htlookup(incname, includetable));
X}
X
X
X
X/*
X * mkdepend() creates include file dependencies for object files and installs
X * them to dependency list dlp. Returns a pointer to the dependency list.
X */
XDLIST *
Xmkdepend()
X{
X	extern SLIST *SRCLIST;		/* source file name list */
X	char *rindex();			/* find last occurrence of character */
X	char *suffix;			/* suffix pointer */
X	DLBLK *dlappend();		/* append dependency list */
X	DLIST *dlinit();		/* initialize dependency list */
X	DLIST *dlist;			/* dependency list */
X	INCBLK *ibp;			/* pointer to chain of include files */
X	INCBLK *readC();		/* read C include-style files */
X	INCBLK *readF();		/* read Fortran include-style files */
X	INCBLK *readP();		/* read Pascal include-style files */
X	int cleanup();			/* remove temporary makefile and exit */
X	int lookuptypeofinclude();	/* look up the brand of include */
X	int slsort();			/* sort singly-linked list */
X	int strcmp();			/* string comparison */
X	int type;			/* source file type */
X	SLBLK *lbp;			/* list block pointer */
X	SLIST *slinit();		/* initialize singly-linked list */
X	void addincdir();		/* add to list of include directories */
X	void rmprinttag();		/* remove "already printed" tags */
X
X	/* initialize include file look-up lists */
X	C_INCDIR = slinit();
X	F_INCDIR = slinit();
X	P_INCDIR = slinit();
X
X	/* add additional include directories */
X	addincdir();
X
X	/* initialize external header file name list */
X	EXTLIST = slinit();
X
X	/* initialize dependency list */
X	dlist = dlinit();
X	 
X	for (lbp = SRCLIST->head; lbp != NULL; lbp = lbp->next)
X		{
X		suffix = rindex(lbp->key, '.');
X		type = lookuptypeofinclude(++suffix);
X		switch (type)
X			{
X			case INCLUDE_C:
X				ibp = readC(lbp->key, 0, lbp->key);
X				break;
X			case INCLUDE_FORTRAN:
X				ibp = readF(lbp->key, 0, lbp->key);
X				break;
X			case INCLUDE_PASCAL:
X				ibp = readP(lbp->key, 0, lbp->key);
X				break;
X			case INCLUDE_NONE:
X				ibp = NULL;
X				break;
X			}
X		if (ibp != NULL)
X			{
X			if (dlappend(type, lbp, ibp, dlist) == NULL)
X				cleanup();
X			}
X		}
X	if (slsort(strcmp, EXTLIST) == NO)
X		cleanup();
X	return(dlist);
X}
X
X
X
X/*
X * notfound() prints a "can't find" filename error message.
X */
Xvoid
Xnotfound(curname, lineno, incname)
X	char *curname;			/* current file name */
X	char *incname;			/* name of include file */
X	int lineno;			/* current line number */
X{
X	if (PGN != NULL && *PGN != '\0')
X		{
X		fprintf(stderr, "%s: ", PGN);
X		}
X	if (*incname == '<')
X		{
X		fprintf(stderr, "\"%s\", line %d: can't find %s\n",
X			curname, lineno, incname);
X		}
X	else	{
X		fprintf(stderr, "\"%s\", line %d: can't find \"%s\"\n",
X			curname, lineno, incname);
X		}
X}
X
X
X
X/*
X * readC() searches C files for included files. Returns a pointer to
X * the chain of include files installed or found in the include file
X * hash table, or null if no include files found.
X */
XINCBLK *
XreadC(lastfile, lastline, curname)
X	char *lastfile;			/* parent file name */
X	int lastline;			/* current line in parent file */
X	char *curname;			/* current file name */
X{
X	register char *p;		/* include string pointer */
X	register FILE *ifp;		/* input file stream */
X	register int c;			/* current character */
X	char incname[PATHSIZE];		/* name of include file */
X	char incpath[PATHSIZE];		/* path to include file */
X	char *slappend();		/* append pathname to list */
X	FILE *fopen();			/* open file */
X	HASHBLK *ftb;			/* fromrule hash table entry block */
X	HASHBLK *htb = NULL;		/* hash table entry block */
X	HASHBLK *instalinclude();	/* install include name in hash table */
X	HASHBLK *lookupinclude();	/* look up include in hash table */
X	INCBLK *i_head = NULL;		/* head of include chain */
X	INCBLK *i_tail = NULL;		/* tail of include chain */
X	INCBLK *inclink();		/* link include file hash blocks */
X	int cleanup();			/* remove temporary makefile and exit */
X	int findinclude();		/* locate include file */
X	int getinclude();		/* get include name from input line */
X	int inctype;			/* origin of include file */
X	int lineno = 1;			/* current line number */
X	int strlen();			/* string length */
X	int type;			/* file type */
X	void notfound();		/* print "can't find" filename msg */
X
X	type = INCLUDE_C;
X
X	if ((ifp = fopen(curname, "r")) == NULL)
X		{
X		if (lastline > 0)
X			fprintf(stderr, "%s: \"%s\", line %d: ", PGN,
X				lastfile, lastline);
X		else
X			fprintf(stderr, "%s: ", PGN);
X		perror(curname);
X		return(NULL);
X		}
X	while ((c = getc(ifp)) != EOF)
X		{
X		if (c != '#')
X			goto nextline;
X		SKIPWHITESPACE(c, ifp);
X		for (p = "include"; (c = getc(ifp)) == *p && *p != '\0' ; p++)
X			continue;
X		if (*p != '\0')
X			goto nextline;
X		if (getinclude(incname, curname, lineno, ifp) == NO)
X			goto nextline;
X		if ((htb = lookupinclude(incname, type)) == NULL)
X			{
X			inctype = findinclude(incpath, incname, curname, type);
X			if (inctype == INTERNAL)
X				{
X				htb = instalinclude(incname, incpath, type);
X				}
X			else if (inctype == EXTERNAL)
X				{
X				htb = instalinclude(incname, incpath, type);
X				if (slappend(incpath, EXTLIST) == NULL)
X					cleanup();
X				}
X			else if (inctype == FROMRULE)
X				{
X				htb = instalinclude(incname, incname, type);
X				ftb = instalinclude(incpath, incpath, type);
X				}
X			else	{
X				notfound(curname, lineno, incname);
X				goto nextline;
X				}
X
X			/* look for nested include files */
X			htb->h_sub = readC(curname, lineno, incpath);
X
X			if (inctype == FROMRULE) 
X				ftb->h_sub = htb->h_sub;
X			}
X		if (i_tail == NULL)
X			{
X			i_head = i_tail = inclink(htb);
X			}
X		else	{
X			i_tail = i_tail->i_next = inclink(htb);
X			}
Xnextline:	while (c != '\n' && c != EOF)
X			c = getc(ifp);
X		lineno++;
X		}
X	fclose(ifp);
X	return(i_head);
X}
X
X
X
X/*
X * readF() searches Fortran files for included files. Returns a pointer
X * to the chain of include files installed or found in the include file
X * hash table, or null if no include files found.
X */
XINCBLK *
XreadF(lastfile, lastline, curname)
X	char *lastfile;			/* parent file name */
X	int lastline;			/* current line in parent file */
X	char *curname;			/* current file name */
X{
X	register char *p;		/* include string pointer */
X	register FILE *ifp;		/* input file stream */
X	register int c;			/* current character */
X	char incname[PATHSIZE];		/* name of include file */
X	char incpath[PATHSIZE];		/* path to include file */
X	char *slappend();		/* append pathname to list */
X	FILE *fopen();			/* open file */
X	HASHBLK *ftb;			/* fromrule hash table entry block */
X	HASHBLK *htb = NULL;		/* hash table entry block */
X	HASHBLK *instalinclude();	/* install include name in hash table */
X	HASHBLK *lookupinclude();	/* look up include in hash table */
X	INCBLK *i_head = NULL;		/* head of include chain */
X	INCBLK *i_tail = NULL;		/* tail of include chain */
X	INCBLK *inclink();		/* link include file hash blocks */
X	int cleanup();			/* remove temporary makefile and exit */
X	int findinclude();		/* locate include file */
X	int getinclude();		/* get include name from input line */
X	int inctype;			/* origin of include file */
X	int lineno = 1;			/* current line number */
X	int strlen();			/* string length */
X	int type;			/* file type */
X	void notfound();		/* print "can't find" filename msg */
X
X	type = INCLUDE_FORTRAN;
X
X	if ((ifp = fopen(curname, "r")) == NULL)
X		{
X		if (lastline > 0)
X			fprintf(stderr, "%s: \"%s\", line %d: ", PGN,
X				lastfile, lastline);
X		else
X			fprintf(stderr, "%s: ", PGN);
X		perror(curname);
X		return(NULL);
X		}
X	while ((c = getc(ifp)) != EOF)
X		{
X		if (c == 'c' || c == 'C' || c == '*' || c == '\n')
X			goto nextline;
X		while ((c = getc(ifp)) == ' ' || c == '\t')
X			continue;
X		for (p = "include"; *p == TOLOWER(c) && *p != '\0'; p++)
X			c = getc(ifp);
X		if (*p != '\0')
X			goto nextline;
X		if (getinclude(incname, curname, lineno, ifp) == NO)
X			goto nextline;
X		if ((htb = lookupinclude(incname, type)) == NULL)
X			{
X			inctype = findinclude(incpath, incname, curname, type);
X			if (inctype == INTERNAL)
X				{
X				htb = instalinclude(incname, incpath, type);
X				}
X			else if (inctype == EXTERNAL)
X				{
X				htb = instalinclude(incname, incpath, type);
X				if (slappend(incpath, EXTLIST) == NULL)
X					cleanup();
X				}
X			else if (inctype == FROMRULE)
X				{
X				htb = instalinclude(incname, incname, type);
X				ftb = instalinclude(incpath, incpath, type);
X				}
X			else	{
X				notfound(curname, lineno, incname);
X				goto nextline;
X				}
X
X			/* look for nested include files */
X			htb->h_sub = readF(curname, lineno, incpath);
X
X			if (inctype == FROMRULE) 
X				ftb->h_sub = htb->h_sub;
X			}
X		if (i_tail == NULL)
X			{
X			i_head = i_tail = inclink(htb);
X			}
X		else	{
X			i_tail = i_tail->i_next = inclink(htb);
X			}
Xnextline:	while (c != '\n' && c != EOF)
X			c = getc(ifp);
X		lineno++;
X		}
X	fclose(ifp);
X	return(i_head);
X}
X
X
X
X/*
X * readP() searches Pascal files for included files. Returns a pointer
X * to the chain of include files installed or found in the include file
X * hash table, or null if no include files found.
X */
XINCBLK *
XreadP(lastfile, lastline, curname)
X	char *lastfile;			/* parent file name */
X	int lastline;			/* current line in parent file */
X	char *curname;			/* current file name */
X{
X	register char *p;		/* include string pointer */
X	register FILE *ifp;		/* input file stream */
X	register int c;			/* current character */
X	char incname[PATHSIZE];		/* name of include file */
X	char incpath[PATHSIZE];		/* path to include file */
X	char *slappend();		/* append pathname to list */
X	FILE *fopen();			/* open file */
X	HASHBLK *ftb;			/* fromrule hash table entry block */
X	HASHBLK *htb = NULL;		/* hash table entry block */
X	HASHBLK *instalinclude();	/* install include name in hash table */
X	HASHBLK *lookupinclude();	/* look up include in hash table */
X	INCBLK *i_head = NULL;		/* head of include chain */
X	INCBLK *i_tail = NULL;		/* tail of include chain */
X	INCBLK *inclink();		/* link include file hash blocks */
X	int cleanup();			/* remove temporary makefile and exit */
X	int findinclude();		/* locate include file */
X	int getinclude();		/* get include name from input line */
X	int inctype;			/* origin of include file */
X	int lineno = 1;			/* current line number */
X	int strlen();			/* string length */
X	int type;			/* file type */
X	void notfound();		/* print "can't find" filename msg */
X
X	type = INCLUDE_PASCAL;
X
X	if ((ifp = fopen(curname, "r")) == NULL)
X		{
X		if (lastline > 0)
X			fprintf(stderr, "%s: \"%s\", line %d: ", PGN,
X				lastfile, lastline);
X		else
X			fprintf(stderr, "%s: ", PGN);
X		perror(curname);
X		return(NULL);
X		}
X	while ((c = getc(ifp)) != EOF)
X		{
X		if (c != '#')
X			goto nextline;
X		while ((c = getc(ifp)) == ' ' || c == '\t')
X			continue;
X		for (p = "include"; *p == TOLOWER(c) && *p != '\0'; p++)
X			c = getc(ifp);
X		if (*p != '\0')
X			goto nextline;
X		if (getinclude(incname, curname, lineno, ifp) == NO)
X			goto nextline;
X		if ((htb = lookupinclude(incname, type)) == NULL)
X			{
X			inctype = findinclude(incpath, incname, curname, type);
X			if (inctype == INTERNAL)
X				{
X				htb = instalinclude(incname, incpath, type);
X				}
X			else if (inctype == EXTERNAL)
X				{
X				htb = instalinclude(incname, incpath, type);
X				if (slappend(incpath, EXTLIST) == NULL)
X					cleanup();
X				}
X			else if (inctype == FROMRULE)
X				{
X				htb = instalinclude(incname, incname, type);
X				ftb = instalinclude(incpath, incpath, type);
X				}
X			else	{
X				notfound(curname, lineno, incname);
X				goto nextline;
X				}
X
X			/* look for nested include files */
X			htb->h_sub = readP(curname, lineno, incpath);
X
X			if (inctype == FROMRULE) 
X				ftb->h_sub = htb->h_sub;
X			}
X		if (i_tail == NULL)
X			{
X			i_head = i_tail = inclink(htb);
X			}
X		else	{
X			i_tail = i_tail->i_next = inclink(htb);
X			}
Xnextline:	while (c != '\n' && c != EOF)
X			c = getc(ifp);
X		lineno++;
X		}
X	fclose(ifp);
X	return(i_head);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/depend.c"
fi
if `test ! -s src/dlist.c`
then
echo "x - src/dlist.c"
sed 's/^X//' > src/dlist.c << '@\End\of\File\'
X/* $Header: dlist.c,v 1.1 85/04/23 13:56:29 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <stdio.h>
X#include "Mkmf.h"
X#include "dlist.h"
X#include "hash.h"
X#include "null.h"
X#include "slist.h"
X#include "yesno.h"
X
Xstatic HASHBLK *printtag = NULL;	/* include files already printed */
Xstatic int COLUMN;			/* last column printed */
X
X/*
X * dlappend() adds a dependency chain block to the end of a list of
X * dependency chain blocks. Each dependency chain block consists of a pointer
X * to a source file name block contained in a singly-linked list, and a pointer
X * to the head of the dependent list of included files. Returns a pointer to
X * the dependency chain block, or a null pointer if out of memory.
X */
XDLBLK *
Xdlappend(srctyp, srcblk, incblk, dlist)
X	int srctyp;			/* source file type */
X	SLBLK *srcblk;			/* pointer to the source file block */
X	INCBLK *incblk;			/* included file dependency chain */
X	DLIST *dlist;			/* pointer to list head block */
X{
X	char *malloc();			/* memory allocator */
X	DLBLK *dblk;			/* pointer to dependency list block */
X
X	if (dlist == NULL)
X		return(NULL);
X	if ((dblk = (DLBLK *) malloc(sizeof(DLBLK))) == NULL)
X		{
X		warn("out of memory");
X		return(NULL);
X		}
X	dblk->d_src = srcblk;
X	dblk->d_type = srctyp;
X	dblk->d_incl = incblk;
X	dblk->d_next = NULL;
X	if (dlist->d_tail == NULL)
X		{
X		dlist->d_head = dlist->d_tail = dblk;
X		}
X	else	{
X		dlist->d_tail = dlist->d_tail->d_next = dblk;
X		}
X	return(dblk);
X}
X
X
X
X/*
X * dlinit() returns a pointer to the head block of a dependency list, or
X * null pointer if out of memory.
X */
XDLIST *
Xdlinit()
X{
X	char *malloc();			/* memory allocator */
X	DLIST *dlist;			/* pointer to list head block */
X
X	if ((dlist = (DLIST *) malloc(sizeof(DLIST))) == NULL)
X		{
X		warn("out of memory");
X		return(NULL);
X		}
X	dlist->d_head = dlist->d_tail = NULL;
X	return(dlist);
X}
X
X
X
X/*
X * dlprint() appends the object-include file dependencies to the end of
X * a makefile. Transitive closure is checked by making suring that an
X * object-include file dependency is not generated if the source file is
X * included in another file.
X */
Xvoid
Xdlprint(dlist, ofp)
X	DLIST *dlist;			/* dependency list */
X	FILE *ofp;			/* output stream */
X{
X	DLBLK *dblk;			/* pointer to dependency list block */
X	HASHBLK *lookupinclude();	/* look up include name in hash table */
X	INCBLK *iblk;			/* cur. include file hash table blk */
X	void putinchain();		/* output nested subinclude filenames */
X	void putobjd();			/* output object file name */
X	void rmprinttag();		/* remove "already printed" tags */
X
X	fprintf(ofp, "%s\n", DEPENDMARK);
X	for (dblk=dlist->d_head; dblk != NULL; dblk=dblk->d_next)
X		{
X		if (lookupinclude(dblk->d_src->key, dblk->d_type) == NULL)
X			{
X			putobjd(dblk->d_src, ofp);
X			for (iblk=dblk->d_incl; iblk != NULL; iblk=iblk->i_next)
X				{
X				putinchain(iblk->i_hblk, ofp);
X				}
X			fprintf(ofp, "\n");
X			rmprinttag();
X			}
X		}
X}
X
X
X
X/*
X * putinchain() outputs a chain of nested include file names. It changes
X * the sign of each chain block h_val field as it traverses the chain to
X * detect looping.
X */
Xstatic void
Xputinchain(htb, ofp)
X	HASHBLK *htb;			/* hash table blk including chain */
X	FILE *ofp;			/* output stream */
X{
X	INCBLK *iblk;			/* cur. include file hash table blk */
X	void putinclude();		/* output include file pathname */
X	void putinchain();		/* output nested subinclude file names*/
X
X	putinclude(htb, ofp);
X	htb->h_val = -htb->h_val;
X	for (iblk=htb->h_sub; iblk != NULL; iblk=iblk->i_next)
X		{
X		if (iblk->i_hblk->h_val < 0)
X			{
X			if (iblk->i_loop == NO)
X				{
X				warn2("recursive include nesting of \"%s\" in \"%s\"",
X				      iblk->i_hblk->h_def, htb->h_def);
X				iblk->i_loop = YES;
X				}
X			continue;
X			}
X		putinchain(iblk->i_hblk, ofp);
X		}
X	htb->h_val = -htb->h_val;
X}
X
X
X
X#define MAXLINE		80
X#define	TABSIZE		8
X
X/*
X * putinclude() writes an include file pathname to stream ofp if
X * if it has not already been written on the current dependency line.
X * and adds the hash block containing the file pathname to the
X * "already printed" printtag list. The last block on the list
X * points back onto itself rather than at NULL so that the non-NULL
X * tag will indicate that the filename has already been seen.
X */
Xstatic void
Xputinclude(htb, ofp)
X	HASHBLK *htb;			/* include file hash block */
X	FILE *ofp;			/* output stream */
X{
X	if (htb->h_tag == NULL)
X		{
X		COLUMN += htb->h_val + 1;
X		if (COLUMN >= (MAXLINE - 2))
X			{
X			fprintf(ofp, " \\\n\t%s", htb->h_def);
X			COLUMN = htb->h_val + TABSIZE;
X			}
X		else	{
X			fprintf(ofp, " %s", htb->h_def);
X			}
X		/* add to "already printed" filenames */
X		htb->h_tag = (printtag == NULL) ? htb :printtag;
X		printtag = htb;
X		}
X}
X
X
X
X/*
X * putobjd() writes an object file dependency name.
X */
Xstatic void
Xputobjd(srcblk, ofp)
X	SLBLK *srcblk;			/* source file name list block */
X	FILE *ofp;			/* output stream */
X{
X	extern char OBJSFX[];		/* object file name suffix */
X	int strlen();			/* string length */
X	void putobj();			/* output object file name */
X
X	COLUMN = strlen(srcblk->key) + strlen(OBJSFX) + 1;
X	putobj(srcblk->key, ofp);
X	fprintf(ofp, ":");
X}
X
X
X
X/*
X * rmprinttag() removes the chain of tags indicating that an include
X * file dependency has already been printed for the current source file.
X */
Xstatic void
Xrmprinttag()
X{
X	register HASHBLK *curhtb;	/* current hash table block */
X	register HASHBLK *nxthtb;	/* next hash table block */
X
X	for (curhtb = printtag; curhtb != NULL; curhtb = nxthtb)
X		{
X		nxthtb = curhtb->h_tag;
X		curhtb->h_tag = NULL;
X		}
X	printtag = NULL;
X}
@\End\of\File\
else
  echo "shar: Will not over write src/dlist.c"
fi
echo "Finished archive 1 of 2"
# to concatenate archives, remove anything after this line
exit 0

ljz@fxgrp.UUCP (Lloyd Zusman) (12/26/87)

I hope I am posting this to the right person.  I assume you are
the moderator of comp.sources.misc.

In a recent posting I mentioned a program called "mkmf" which
makes makefiles.  Lots of people have sent me mail requesting
this software, so here it is.  In the aforementioned posting,
I said this program is "netware", but apparently it has not
been posted on the net (???).  It is, however, definitely in
the public domain.

It comes in two pieces.  Here is part 2.

Enjoy.

 Lloyd Zusman
 Master Byte Software
 Los Gatos, California	    	    	Internet:   fxgrp!ljz@ames.arpa
 "We take things well in hand."	    	UUCP:	    ...!ames!fxgrp!ljz

#--------------------------Cut Here--------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before the "#! /bin/sh" line,
# then unpack it by saving it in a file and typing "sh file."
#
# Wrapped by Lloyd Zusman (ljz) at fxgrp on Tue Dec 22 12:53:36 1987
#
# unpacks with default permissions
#
# Contents : src/editmf.c src/getcwp.c src/getproject.c src/hash.c
#	src/iolin.c src/macro.c src/misc.c src/mustfopen.c src/optpath.c
#	src/pathcat.c src/pathhead.c src/pperror.c src/rule.c src/slappend.c
#	src/slinit.c src/slsort.c src/strpcpy.c src/strsav.c src/suffix.c
#	src/usage.c src/warn.c src/warn2.c src/warns.c src/Mkmf.h
#	src/defaultrul.h src/defaultsfx.h src/dlist.h src/getarg.h src/hash.h
#	src/macro.h src/null.h src/path.h src/rule.h src/sccsid.h src/slist.h
#	src/spms.h src/suffix.h src/system.h src/target.h src/yesno.h
#	src/oMakefile x.Makefile/t.Makefile x.Makefile/Makefile
#	x.Makefile/l.Makefile x.Makefile/p.Makefile
#
if `test ! -d src`
then
  mkdir src
  echo "mkdir src"
fi
if `test ! -s src/editmf.c`
then
echo "x - src/editmf.c"
sed 's/^X//' > src/editmf.c << '@\End\of\File\'
X/* $Header: editmf.c,v 1.4 85/05/02 07:51:40 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <ctype.h>
X#include <signal.h>
X#include <stdio.h>
X#include "Mkmf.h"
X#include "dlist.h"
X#include "hash.h"
X#include "macro.h"
X#include "null.h"
X#include "slist.h"
X#include "system.h"
X#include "yesno.h"
X
Xstatic char *Mftemp;			/* temporary makefile */
X
X/*
X * editmf() replaces macro definitions within a makefile.
X */
Xvoid
Xeditmf(mfname, mfpath)
X	char *mfname;			/* makefile name */
X	char *mfpath;			/* makefile template pathname */
X{
X	register char *bp;		/* buffer pointer */
X	extern char IOBUF[];		/* I/O buffer line */
X	extern int DEPEND;		/* dependency analysis? */
X	extern SLIST *EXTLIST;		/* external header file name list */
X	extern SLIST *HEADLIST;		/* header file name list */
X	extern SLIST *LIBLIST;		/* library pathname list */
X	extern SLIST *SRCLIST;		/* source file name list */
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	char *findmacro();		/* is the line a macro definition? */
X	char *getlin();			/* get a line from input stream */
X	char *mktemp();			/* make file name */
X	char mnam[MACRONAMSIZE];	/* macro name buffer */
X	DLIST *dlp;			/* dependency list */
X	DLIST *mkdepend();		/* generate object-include file deps */
X	FILE *ifp;			/* input stream */
X	FILE *mustfopen();		/* must open file or die */
X	FILE *ofp;			/* output stream */
X	HASHBLK *htb;			/* hash table block */
X	HASHBLK *htlookup();		/* find hash table entry */
X	int cleanup();			/* remove temporary makefile and exit */
X	void dlprint();			/* print dependency list */
X	void purgcontinue();		/* get rid of continuation lines */
X	void putmacro();		/* put macro defs from table */
X	void putlin();			/* put a makefile line */
X	void putobjmacro();		/* put object file name macro def */
X	void putslmacro();		/* put macro defs from linked list */
X
X	ifp = mustfopen(mfpath, "r");
X	Mftemp = mktemp("mkmfXXXXXX");
X
X	signal(SIGHUP, cleanup);
X	signal(SIGINT, cleanup);
X	signal(SIGQUIT, cleanup);
X
X	ofp = mustfopen(Mftemp, "w");
X	if (DEPEND)
X		{
X		dlp = mkdepend();
X		}
X
X	while (getlin(ifp) != NULL)
X		{
X		if (DEPEND && EQUAL(IOBUF, DEPENDMARK))
X			break;
X		for (bp = IOBUF; *bp == ' '; bp++)
X			continue;
X		if (isalnum(*bp) && findmacro(mnam, bp) != NULL)
X			{
X			if ((htb = htlookup(mnam, MDEFTABLE)) != NULL)
X				{
X				if (htb->h_val == VREADWRITE)
X					{
X					putmacro(htb->h_def, ofp);
X					purgcontinue(ifp);
X					}
X				else	{
X					putlin(ofp);
X					}
X				}
X			else if (EQUAL(mnam, MHEADERS))
X				{
X				putslmacro(HEADLIST, ofp);
X				purgcontinue(ifp);
X				}
X			else if (EQUAL(mnam, MOBJECTS))
X				{
X				putobjmacro(ofp);
X				purgcontinue(ifp);
X				}
X			else if (EQUAL(mnam, MSOURCE))
X				{
X				putslmacro(SRCLIST, ofp);
X				purgcontinue(ifp);
X				}
X			else if (EQUAL(mnam, MEXTERNALS))
X				{
X				if (DEPEND)
X					{
X					putslmacro(EXTLIST, ofp);
X					purgcontinue(ifp);
X					}
X				else	{
X					putlin(ofp);
X					}
X				}
X			else if (EQUAL(mnam, MLIBLIST) && LIBLIST != NULL)
X				{
X				putslmacro(LIBLIST, ofp);
X				purgcontinue(ifp);
X				}
X			else	{
X				putlin(ofp);
X				}
X			}
X		else	{
X			putlin(ofp);
X			}
X		}
X	fclose(ifp);
X	if (DEPEND)
X		{
X		dlprint(dlp, ofp);
X		}
X	fclose(ofp);
X
X	signal(SIGHUP, SIG_IGN);
X	signal(SIGINT, SIG_IGN);
X	signal(SIGQUIT, SIG_IGN);
X
X	RENAME(Mftemp, mfname);
X}
X
X
X
X/*
X * cleanup() removes the temporary makefile and dependency file, and
X * calls exit(1).
X */
Xcleanup()
X{
X	signal(SIGHUP, cleanup);
X	signal(SIGINT, cleanup);
X	signal(SIGQUIT, cleanup);
X
X	unlink(Mftemp);
X	exit(1);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/editmf.c"
fi
if `test ! -s src/getcwp.c`
then
echo "x - src/getcwp.c"
sed 's/^X//' > src/getcwp.c << '@\End\of\File\'
X/* $Header: getcwp.c,v 1.1 85/03/14 16:58:54 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * getcwp() returns the pathname of the current working project. If the
X * PROJECT environment variable is undefined or a null string, null is
X * returned.
X */
X#include "null.h"
X
Xchar *
Xgetcwp()
X{
X	extern char *_PROJECT;		/* project root directory pathname */
X	void getproject();		/* get PROJECT environment variable */
X
X	if (_PROJECT == NULL)
X		getproject();
X	return(_PROJECT);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/getcwp.c"
fi
if `test ! -s src/getproject.c`
then
echo "x - src/getproject.c"
sed 's/^X//' > src/getproject.c << '@\End\of\File\'
X/* $Header: getproject.c,v 1.1 85/03/14 16:59:01 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * getproject() saves the contents of the PROJECT environment variable.
X * If the PROJECT variable is undefined or a null string, null is returned.
X */
X#include "null.h"
X
Xchar *_PROJECT = NULL;			/* project root directory pathname */
X
Xvoid
Xgetproject()
X{
X	register char *pv;		/* ptr to start of PROJECT variable */
X	char *getenv();			/* get environment variable */
X	char *strsav();			/* save a string somewhere */
X
X	if ((pv = getenv("PROJECT")) != NULL && *pv != '\0')
X		_PROJECT = strsav(pv);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/getproject.c"
fi
if `test ! -s src/hash.c`
then
echo "x - src/hash.c"
sed 's/^X//' > src/hash.c << '@\End\of\File\'
X/* $Header: hash.c,v 1.1 85/03/14 15:38:16 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include "null.h"
X#include "hash.h"
X#include "macro.h"
X
X/*
X * hthash() returns a hash value for string, s.
X */
Xhthash(s, hash)
X	register char *s;		/* string */
X	HASH *hash;			/* hash table */
X{
X	register int hashval;		/* hash value for string */
X
X	for (hashval = 0; *s != '\0'; s++)
X		hashval += *s;
X	return(hashval % hash->hashsiz);
X}
X
X
X
X/*
X * htinit() returns a pointer to a new hash table, or a null pointer if
X * out of memory.
X */
XHASH *
Xhtinit(hashsiz)
X	unsigned int hashsiz;		/* hash table size */
X{
X	char *malloc();			/* allocate memory */
X	char *calloc();			/* allocate and zero memory */
X	HASH *ht;			/* pointer to hash table struct */
X	HASHBLK **pt;			/* pointer to hash pointer table */
X
X	if ((ht = (HASH *) malloc(sizeof(HASH))) == NULL ||
X	    (pt = (HASHBLK **) calloc(hashsiz, sizeof(HASHBLK *))) == NULL)
X		{
X		warn("out of memory");
X		return(NULL);
X		}
X	ht->hashtab = pt;
X	ht->hashsiz = hashsiz;
X	return(ht);
X}
X
X
X
X/*
X * htinstall() installs a new entry in a hash table if it doesn't already
X * exist. If it does, the old definition and value is superseded. Returns
X * a pointer to the entry, or null if out of memory.
X */
XHASHBLK *
Xhtinstall(key, def, val, hash)
X	char *key;			/* key for hash table entry */
X	char *def;			/* definition string */
X	int val;			/* integer value */
X	HASH *hash;			/* hash table */
X{
X	char *malloc();			/* memory allocator */
X	char *strsav();			/* save string somewhere */
X	HASHBLK *htb;			/* hash table entry block */
X	HASHBLK *htlookup();		/* find hash table entry */
X	int hashval;			/* hash value for key */
X	int hthash();			/* calculate hash value */
X
X	if ((htb = htlookup(key, hash)) == NULL)
X		{			/* not found */
X		if ((htb = (HASHBLK *) malloc(sizeof(HASHBLK))) == NULL)
X			return(NULL);
X		if ((htb->h_key = strsav(key)) == NULL)
X			return(NULL);
X		hashval = hthash(key, hash);
X		htb->h_next = (hash->hashtab)[hashval];
X		(hash->hashtab)[hashval] = htb;
X		htb->h_sub = NULL;
X		htb->h_tag = NULL;
X		}
X	else	{			/* found */
X		free(htb->h_def);	/* free previous definition */
X		}
X	if ((htb->h_def = strsav(def)) == NULL)
X		return(NULL);
X	htb->h_val = val;
X	return(htb);
X}
X
X
X
X/*
X * htlookup() returns a pointer to a hash table entry if found, otherwise null.
X */
XHASHBLK *
Xhtlookup(key, hash)
X	char *key;			/* key for hash table entry */
X	HASH *hash;			/* hash table */
X{
X	HASHBLK *htb;			/* hash table entry block */
X	int hthash();			/* calculate hash value */
X
X	for (htb = (hash->hashtab)[hthash(key, hash)]; htb != NULL; htb = htb->h_next)
X		if (EQUAL(htb->h_key, key))
X			return(htb);	/* found */
X	return(NULL);			/* not found */
X}
X
X
X
X/*
X * htrm() removes a hash table entry. If key is null, the entire hash
X * table is removed.
X */
Xvoid
Xhtrm(key, hash)
X	char *key;			/* key for hash table entry */
X	HASH *hash;			/* hash table */
X{
X	HASHBLK *htbrm();		/* remove hash table block */
X	HASHBLK *htc;			/* first hash table block in chain */
X	int hashval;			/* hash value for key */
X	int hthash();			/* compute hash value */
X	int i;				/* hash table index */
X
X	if (key == NULL)
X		{
X		for (i = 0; i < hash->hashsiz; i++)
X			if ((htc = (hash->hashtab)[i]) != NULL)
X				htc = htbrm(key, htc);
X		free((char *) hash);
X		}
X	else	{
X		hashval = hthash(key, hash);
X		if ((htc = (hash->hashtab)[hashval]) != NULL)
X			(hash->hashtab)[hashval] = htbrm(key, htc);
X		}
X}
X
X
X
X/*
X * htbrm() removes a hash table block identified by key. If key is null, the
X * entire chain is removed. Returns a pointer to the first block in the chain.
X */
XHASHBLK *
Xhtbrm(key, htc)
X	char *key;			/* key string */
X	HASHBLK *htc;			/* hash table block chain */
X{
X	HASHBLK *curblk;		/* current list block */
X	HASHBLK *nxtblk;		/* next list block */
X	HASHBLK *prvblk;		/* previous list block */
X
X	if (key == NULL)
X		while (htc != NULL)
X			{
X			nxtblk = htc->h_next;
X			free(htc->h_key);
X			free(htc->h_def);
X			free((char *) htc);
X			htc = nxtblk;
X			}
X	else	{
X		/* first block is a special case */
X		if (EQUAL(htc->h_key, key))
X			{
X			nxtblk = htc->h_next;
X			free(htc->h_key);
X			free(htc->h_def);
X			free((char *) htc);
X			htc = nxtblk;
X			}
X		else	{
X			/* remainder of list */
X			prvblk = htc;
X			curblk = htc->h_next;
X			while (curblk != NULL)
X				if (EQUAL(curblk->h_key, key))
X					{
X					prvblk->h_next = curblk->h_next;
X					free(curblk->h_key);
X					free(curblk->h_def);
X					free((char *) curblk);
X					curblk = prvblk->h_next;
X					break;
X					}
X				else	{
X					prvblk = curblk;
X					curblk = curblk->h_next;
X					}
X			}
X		}
X	return(htc);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/hash.c"
fi
if `test ! -s src/iolin.c`
then
echo "x - src/iolin.c"
sed 's/^X//' > src/iolin.c << '@\End\of\File\'
X/* $Header: iolin.c,v 1.1 85/03/14 15:38:25 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <stdio.h>
X#include "yesno.h"
X
Xchar IOBUF[BUFSIZ];			/* I/O line buffer */
Xshort CONTINUE;				/* does the line continue? */
X
X/*
X * getlin() stores a line from input stream in IOBUF. The string is terminated
X * by a newline character which is replaced by a null character. getlin()
X * returns IOBUF, or null pointer upon end of file.
X */
Xchar *
Xgetlin(stream)
X	register FILE *stream;		/* input stream */
X{
X	register int c;			/* current character */
X	register char *iop;		/* IOBUF pointer */
X
X	iop = IOBUF;
X	while ((c = getc(stream)) != '\n' && c != EOF)
X		*iop++ = c;
X	if (c == EOF && iop == IOBUF)
X		return(NULL);
X	if (iop != IOBUF && iop[-1] == '\\')
X		{
X		iop[-1] = '\0';
X		CONTINUE = YES;
X		}
X	else	{
X		iop[0] = '\0';
X		CONTINUE = NO;
X		}
X	return(IOBUF);
X}
X
X
X
X/*
X * purgcontinue() eats up continuation lines from an input stream.
X */
Xvoid
Xpurgcontinue(stream)
X	register FILE *stream;		/* input stream */
X{
X	register int c;			/* current character */
X	register int lastc;		/* previous character */
X
X	if (CONTINUE == YES)
X		{
X		for (;;)
X			{
X			while ((c = getc(stream)) != '\n' && c != EOF)
X				lastc = c;
X			if (c == EOF || (c == '\n' && lastc != '\\'))
X				break;
X			}
X		CONTINUE = NO;
X		}
X}
X
X
X
X/*
X * putlin() writes IOBUF to stream and appends a newline character. If
X * IOBUF holds a CONTINUE line, a `\' precedes the newline.
X */
Xvoid
Xputlin(stream)
X	register FILE *stream;		/* output stream */
X{
X	register int c;			/* current character */
X	register char *iop;		/* IOBUF pointer */
X
X	iop = IOBUF;
X	while (c = *iop++)
X		putc(c, stream);
X	if (CONTINUE == YES)
X		putc('\\', stream);
X	putc('\n', stream);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/iolin.c"
fi
if `test ! -s src/macro.c`
then
echo "x - src/macro.c"
sed 's/^X//' > src/macro.c << '@\End\of\File\'
X/* $Header: macro.c,v 1.3 85/05/02 07:53:52 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <ctype.h>
X#include <stdio.h>
X#include "Mkmf.h"
X#include "hash.h"
X#include "macro.h"
X#include "null.h"
X#include "slist.h"
X#include "yesno.h"
X
Xextern char IOBUF[];			/* I/O buffer line */
X
X/*
X * findmacro() searchs a line for a macro definition. Returns the name,
X * or null if not found.
X */
Xchar *
Xfindmacro(macroname, bp)
X	char *macroname;		/* macro name receiving buffer */
X	register char *bp;		/* buffer pointer */
X{
X	register char *mp;		/* macro name pointer */
X
X	mp = macroname;
X	while(isalnum(*bp))
X		*mp++ = *bp++;
X	*mp = '\0';
X	while(*bp == ' ' || *bp == '\t')
X		bp++;
X	if (*bp != '=')
X		return(NULL);
X	return(macroname);
X}
X	
X
X
X/*
X * getmacro() loads the body of a macro definition into mdefbuf and returns
X * a pointer to mdefbuf. If the macro definition continues on more than
X * one line further lines are fetched from the input stream.
X */
Xchar *
Xgetmacro(mdefbuf, stream)
X	char *mdefbuf;			/* receiving macro definition buffer */
X	FILE *stream;			/* input stream */
X{
X	extern short CONTINUE;		/* does the line continue? */
X	char *getlin();			/* get a line from input stream */
X	register char *bp;		/* buffer pointer */
X	register char *mp;		/* macro definition buffer pointer */
X
X	bp = IOBUF;
X	mp = mdefbuf;
X	while (*bp++ != '=')
X		continue;
X	if (WHITESPACE(*bp))
X		bp++;
X	while (*bp != '\0')
X		*mp++ = *bp++;
X	while (CONTINUE == YES)
X		{
X		*mp++ = ' ';
X		if (getlin(stream) == NULL)
X			break;
X		bp = IOBUF;
X		while (*bp != '\0')
X			*mp++ = *bp++;
X		}
X	*mp = '\0';
X	return(mdefbuf);
X}
X
X
X
X/*
X * putmacro() prints a macro definition from the macro definition table.
X */
Xvoid
Xputmacro(macrovalue, stream)
X	char *macrovalue;		/* value of macro definition */
X	register FILE *stream;		/* output stream */
X{
X	register char *iop;		/* IOBUF pointer */
X	register int c;			/* current character */
X
X	iop = IOBUF;
X	while ((c = *iop++) != '=')
X		putc(c, stream);
X	fprintf(stream, "= %s\n", macrovalue);
X}
X
X
X
X/*
X * putobjmacro() derives and prints object file names from the SRCLIST list.
X */
Xvoid
Xputobjmacro(stream)
X	register FILE *stream;		/* output stream */
X{
X	extern SLIST *SRCLIST;		/* source file name list */
X	register char *iop;		/* IOBUF pointer */
X	register int c;			/* current character */
X	char *rindex();			/* find last occurrence of character */
X	char *suffix;			/* suffix pointer */
X	HASHBLK *lookupinclude();	/* look up include name in hash table */
X	int cnt = 0;			/* number of object filenames printed */
X	int lookuptypeofinclude();	/* look up the brand of include */
X	int type;			/* file type */
X	SLBLK *lbp;			/* list block pointer */
X	void putobj();			/* print object file name */
X
X	iop = IOBUF;
X	while ((c = *iop++) != '=')
X		putc(c, stream);
X	putc('=', stream);
X	for (lbp = SRCLIST->head; lbp != NULL; lbp = lbp->next)
X		{
X		suffix = rindex(lbp->key, '.');
X		type = lookuptypeofinclude(++suffix);
X		if (lookupinclude(lbp->key, type) == NULL)
X			{
X			cnt += 1;
X			if (cnt == 1)
X				{
X				putc(' ', stream);
X				putobj(lbp->key, stream);
X				}
X			else	{
X				fprintf(stream, " \\\n\t\t");
X				putobj(lbp->key, stream);
X				}
X			}
X		}
X	putc('\n', stream);
X}
X
X
X
X/*
X * putslmacro() copies a macro definition from a list.
X */
Xvoid
Xputslmacro(slist, stream)
X	SLIST *slist;			/* singly-linked macro def list */
X	register FILE *stream;		/* output stream */
X{
X	register char *iop;		/* IOBUF pointer */
X	register int c;			/* current character */
X	SLBLK *lbp;			/* list block pointer */
X
X	iop = IOBUF;
X	while ((c = *iop++) != '=')
X		putc(c, stream);
X	putc('=', stream);
X	if (SLNUM(slist) > 0)
X		{
X		lbp = slist->head;
X		fprintf(stream, " %s", lbp->key);
X		}
X	if (SLNUM(slist) > 1)
X		for (lbp = lbp->next; lbp != NULL; lbp = lbp->next)
X			fprintf(stream, " \\\n\t\t%s", lbp->key);
X	putc('\n', stream);
X}
X
X
X
X/*
X * storemacro() stores a macro definition in the macro definition table.
X * Returns integer YES if a macro definition (macro=definition), otherwise
X * NO. exit(1) is called if out of memory.
X */
Xstoremacro(macdef)
X	char *macdef;			/* macro definition string */
X{
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	register int i;			/* macro value index */
X	register int j;			/* macro name index */
X	HASHBLK *htinstall();		/* install hash table entry */
X
X	for (i = 0; macdef[i] != '='; i++)
X		if (macdef[i] == '\0')
X			return(NO);
X	
X	/* removing trailing blanks and tabs from end of macro name */
X	for (j = i; j > 0; j--)
X		if (!WHITESPACE(macdef[j-1]))
X			break;
X	macdef[j] = '\0';
X
X	/* remove leading blanks and tabs from macro value */
X	for (i++; WHITESPACE(macdef[i]); i++)
X		continue;
X	if (htinstall(macdef, macdef+i, VREADWRITE, MDEFTABLE) == NULL)
X		exit(1);
X	return(YES);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/macro.c"
fi
if `test ! -s src/misc.c`
then
echo "x - src/misc.c"
sed 's/^X//' > src/misc.c << '@\End\of\File\'
X/* $Header: misc.c,v 1.6 85/06/27 08:15:57 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <ctype.h>
X#include <stdio.h>
X#include "Mkmf.h"
X#include "hash.h"
X#include "macro.h"
X#include "null.h"
X#include "path.h"
X#include "target.h"
X#include "spms.h"
X#include "suffix.h"
X#include "system.h"
X#include "yesno.h"
X
X/*
X * answer() installs a line from stdin in the macro definition table.
X * exit(1) is called if EOF, error, or out of memory.
X */
Xvoid
Xanswer(mdefkey, mdefval)
X	char *mdefkey;			/* macro definition key */
X	int mdefval;			/* macro definition value */
X{
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	char answerbuf[ANSWERBUFSIZE];	/* answer from stdin */
X	char *gets();			/* get a line from stdin */
X	HASHBLK *htinstall();		/* install hash table entry */
X
X	if (gets(answerbuf) == NULL)
X		exit(1);
X	if (*answerbuf != '\0')
X		if (htinstall(mdefkey, answerbuf, mdefval, MDEFTABLE) == NULL)
X			exit(1);
X}
X
X
X
X/*
X * fastcopy() copies file to stream fp. Returns integer YES if successful,
X * otherwise NO.
X */
Xfastcopy(filename, ofp)
X	char *filename;			/* file to be copied */
X	register FILE *ofp;		/* output stream */
X{
X	register int ifd;		/* input file descriptor */
X	register int n;			/* byte count */
X	char buf[BUFSIZ];		/* I/O buffer */
X
X	if ((ifd = OPEN(filename, 0, 0644)) == -1)
X		{
X		pperror("");
X		return(NO);
X		}
X	while ((n = read(ifd, buf, BUFSIZ)) > 0)
X		write(fileno(ofp), buf, n);
X	close(ifd);
X	return(YES);
X}
X
X
X
X/*
X * findmf() locates the makefile to be edited. The type of makefile
X * is returned in target. The pathname to the makefile is returned
X * in mfpath. Returns YES if makefile or makefile template can be
X * opened, otherwise NO.
X */
Xfindmf(mfname, mfpath, target)
X	char *mfname;			/* name of target makefile */
X	char *mfpath;			/* path to target makefile */
X	TARGET *target;			/* type of makefile target */
X{
X	extern int CFLAG;		/* makefile creation message */
X	char *strcpy();			/* string copy */
X	int readmf();			/* read makefile */
X	int targettype;			/* type of makefile requested */
X	void findmftemplate();		/* find makefile template */
X
X	targettype = target->type;
X	if (FILEXIST(mfname))
X		{
X		if (!FILEWRITE(mfname))
X			{
X			pperror(mfname);
X			target->type = VERROR;
X			return(NO);
X			}
X		if (readmf(mfname, target) == VERROR)
X			return(NO);
X		if (targettype == VUNKNOWN || targettype == target->type)
X			{
X			strcpy(mfpath, mfname);
X			return(YES);
X			}
X		}
X	target->type = (targettype == VLIBRARY) ? VLIBRARY : VPROGRAM;
X	findmftemplate(mfpath, target);
X	if (readmf(mfpath, target) == VERROR)
X		return(NO);
X	else if (CFLAG == YES)
X		warn2("creating %s from template %s", mfname, mfpath);
X	return(YES);
X}
X
X
X
X/*
X * findmftemplate() returns the pathname of a makefile template in mfpath.
X */
Xvoid
Xfindmftemplate(mfpath, target)
X	char *mfpath;			/* path to target makefile */
X	TARGET *target;			/* type of makefile target */
X{
X	extern char *L_MAKEFILE;	/* library makefile template */
X	extern char *P_MAKEFILE;	/* program makefile template */
X	char *cwp;			/* current project pathname pointer */
X	char *getcwp();			/* get current project pathname */
X	char *pathcat();		/* pathname concatenation */
X	char *strcpy();			/* string copy */
X
X	cwp = getcwp();
X	if (target->type == VPROGRAM)
X		{
X		if (*P_MAKEFILE == _RDIRC)
X			strcpy(mfpath, P_MAKEFILE);
X		else if (cwp == NULL ||
X			 !FILEXIST(pathcat(mfpath, pathcat(mfpath, cwp, "lib"), P_MAKEFILE)))
X			pathcat(mfpath, SPMSLIB, P_MAKEFILE);
X		}
X	else if (target->type == VLIBRARY)
X		{
X		if (*L_MAKEFILE == _RDIRC)
X			strcpy(mfpath, L_MAKEFILE);
X		else if (cwp == NULL ||
X			 !FILEXIST(pathcat(mfpath, pathcat(mfpath, cwp, "lib"), L_MAKEFILE)))
X			pathcat(mfpath, SPMSLIB, L_MAKEFILE);
X		}
X	else
X		warn("unknown template request");
X}
X
X
X
X/*
X * gettoken() copies the next token from token buffer to token. Returns a
X * pointer to the first character after the token, or null upon reaching
X * the end of the token buffer.
X */
Xchar *
Xgettoken(token, tp)
X	register char *token;		/* receiving token */
X	register char *tp;		/* token buffer pointer */
X{
X	while (isspace(*tp) && *tp != '\0')
X		tp++;
X	if (*tp == '\0')
X		{
X		*token = '\0';
X		return(NULL);
X		}
X	while (!isspace(*tp) && *tp != '\0')
X		*token++ = *tp++;
X	*token = '\0';
X	return(tp);
X}
X
X
X
X/*
X * putobj() converts a source file name to an object file name and then
X * writes the file name to stream.
X */
Xvoid
Xputobj(s, stream)
X	register char *s;		/* source file name */
X	register FILE *stream;		/* output stream */
X{
X	extern char OBJSFX[];		/* object file name suffix */
X	register char *dot;		/* pointer to suffix */
X	char *rindex();			/* last occurrence of character */
X
X	dot = rindex(s, '.');
X	while (s != dot)
X		putc(*s++, stream);
X	fprintf(stream, "%s", OBJSFX);
X}
X
X
X
X/*
X * readmf() reads a makefile and loads CFLAGS, FFLAGS, and SUFFIX definitions
X * into the macro definition table if they do not already exist. Returns
X * integer VLIBRARY, VPROGRAM, or VUNKNOWN according to the type of makefile,
X * or VERROR if cannot open makefile.
X */
Xreadmf(mfname, target)
X	char *mfname;			/* name of makefile */
X	TARGET *target;			/* type of makefile target */
X{
X	register char *bp;		/* buffer pointer */
X	extern char IOBUF[];		/* I/O buffer line */
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	char *findmacro();		/* is the line a macro definition? */
X	char *findrule();		/* is the line a rule definition? */
X	char *getlin();			/* get a line from input stream */
X	char *getmacro();		/* get macro def from input stream */
X	char macrodef[MACRODEFSIZE];	/* macro definition buffer */
X	char macroname[MACRONAMSIZE];	/* macro name buffer */
X	char rulename[2*SUFFIXSIZE+3];	/* transformation rule name */
X	FILE *fopen();			/* open file */
X	FILE *fp;			/* file pointer */
X	HASHBLK *htinstall();		/* install hash table entry */
X	HASHBLK *htlookup();		/* find hash table entry */
X	int storerule();		/* store transformation rule */
X
X	target->type = target->dest = VUNKNOWN;
X	if ((fp = fopen(mfname, "r")) == NULL)
X		{
X		pperror(mfname);
X		target->type = VERROR;
X		return(target->type);
X		}
X	while (getlin(fp) != NULL)
X		{
X		if (EQUAL(IOBUF, DEPENDMARK))
X			break;
X		for (bp = IOBUF; *bp == ' '; bp++)
X			continue;
X		if (isalnum(*bp) && findmacro(macroname, bp) != NULL)
X			{
X			if (EQUAL(macroname, MPROGRAM))
X				{
X				target->type = VPROGRAM;
X				continue;
X				}
X			else if (EQUAL(macroname, MLIBRARY))
X				{
X				target->type = VLIBRARY;
X				continue;
X				}
X			else if (EQUAL(macroname, MDESTDIR))
X				{
X				target->dest = VDESTDIR;
X				continue;
X				}
X
X			/* does macro definition already exist? */
X			if (htlookup(macroname, MDEFTABLE) != NULL)
X				continue;
X
X			if (EQUAL(macroname, MCFLAGS) ||
X			    EQUAL(macroname, MFFLAGS) ||
X			    EQUAL(macroname, MPFLAGS) ||
X			    EQUAL(macroname, MSUFFIX))
X				{
X				if (htinstall(macroname, getmacro(macrodef, fp),
X					      VREADONLY, MDEFTABLE) == NULL)
X					{
X					fclose(fp);
X					return(NO);
X					}
X				}
X			}
X		else if (*bp == '.' && findrule(rulename, bp) != NULL)
X			{
X			if (storerule(rulename) == NO)
X				{
X				fclose(fp);
X				return(NO);
X				}
X			}
X		}
X	fclose(fp);
X	return(target->type);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/misc.c"
fi
if `test ! -s src/mustfopen.c`
then
echo "x - src/mustfopen.c"
sed 's/^X//' > src/mustfopen.c << '@\End\of\File\'
X/* $Header: mustfopen.c,v 1.2 85/03/17 12:51:04 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * mustfopen() opens a file in the manner of fopen(3). However, if the file
X * cannot be accessed, exit(1) is called.
X */
X#include <stdio.h>
X
Xextern char *PGN;		/* program name */
X
XFILE *
Xmustfopen(filename,mode)
X	char *filename;
X	char *mode;
X{
X	FILE *stream;			/* file stream */
X
X	if ((stream = fopen(filename,mode)) == NULL)
X		{
X		if (*PGN != '\0')
X			fprintf(stderr, "%s: ", PGN);
X		fprintf(stderr, "can't open %s\n",filename);
X		exit(1);
X		}
X	return(stream);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/mustfopen.c"
fi
if `test ! -s src/optpath.c`
then
echo "x - src/optpath.c"
sed 's/^X//' > src/optpath.c << '@\End\of\File\'
X/* $Header: optpath.c,v 1.2 85/05/06 13:32:05 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * optpath() condenses a pathname by eliminating adjacent separator
X * characters, and current and parent directory names. If optpath()
X * encounters a parent directory, it backtracks to eliminate the
X * previous directory. If the beginning of the pathname is reached
X * during backtracking, then if the pathname is absolute, the parent
X * directory is purged, otherwise it is shifted to the beginning of
X * pathname. Special care is taken not to clobber a shifted parent
X * by using a guard pointer. Returns pathname.
X */
X#include "path.h"
X
X#define absolute_path	(*pathname == _RDIRC)
X
Xstatic char parentdir[] = PARENTDIR;	/* parent directory name */
X
Xchar *
Xoptpath(pathname)
X	register char *pathname;	/* pathname to be optimized */
X{
X	register char *bp;		/* back pathname pointer */
X	register char *fp;		/* forward pathname pointer */
X	register char *up;		/* pathname update guard pointer */
X	char p1;			/* 1st parent directory character */
X	char p2;			/* 2nd parent directory character */
X
X	p1 = parentdir[0];
X	p2 = parentdir[1];
X
X	bp = fp = up = pathname;
X
X	/* elimination of initial "./" causes no harmful side-effects */
X	if (fp[0] == _CDIRC && fp[1] == _PSC) fp += 2;
X
X	while (*fp != '\0')
X		if (fp[0] == _PSC)
X			if (fp[1] == _PSC || fp[1] == '\0')
X				fp += 1;	/* "//" or trailing `/' */
X			else if (fp[1]==_CDIRC && (fp[2]==_PSC || fp[2]=='\0'))
X				fp += 2;	/* `.' */
X			else if ((fp[1] == p1 && fp[2] == p2) &&
X				 (fp[3] == _PSC || fp[3] == '\0'))
X				{	/* ".." (don't backtrack over a "..") */
X				if (absolute_path || 
X				   (bp > up && bp-2 < pathname) ||
X				   (bp > up && (bp[-2] != p1 || bp[-1] != p2)))
X					{
X					while (bp > up && *--bp != _PSC)
X						continue;
X					}
X				else	{
X					/* don't clobber separator character */
X					if (bp[0] == _PSC) bp++;
X					bp[0] = fp[1];
X					bp[1] = fp[2];
X					bp[2] = fp[3];
X					up = bp += 2;
X					}
X				fp += 3;
X				}
X			else	{
X				*bp++ = *fp++;
X				}
X		else	{
X			*bp++ = *fp++;
X			}
X	if (bp == pathname && *pathname != '\0')
X		*bp++ = (absolute_path) ? _RDIRC : _CDIRC;
X	*bp = '\0';
X	return(pathname);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/optpath.c"
fi
if `test ! -s src/pathcat.c`
then
echo "x - src/pathcat.c"
sed 's/^X//' > src/pathcat.c << '@\End\of\File\'
X/* $Header: pathcat.c,v 1.2 85/03/17 15:23:03 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * pathcat() concatenates path components p1 and p2 into character buffer
X * p1_p2. Returns p1_p2.
X */
X#include <stdio.h>
X#include "path.h"
X
Xextern char *PGN;			/* program name */
X
Xchar *
Xpathcat(p1_p2, p1, p2)
X	register char *p1;
X	register char *p2;
X	register char *p1_p2;
X{
X	register int plen;		/* maximum pathname length */
X	char *sp1_p2;			/* start of p1_p2 */
X
X	sp1_p2 = p1_p2;
X	for (plen = PATHSIZE; plen > 0; plen--, p1_p2++, p1++)
X		if ((*p1_p2 = *p1) == '\0')
X			break;
X	if (*p2 != '\0' && plen > 0)
X		{
X		if (p1_p2 != sp1_p2 && p1_p2[-1] != _PSC)
X			{
X			*p1_p2++ = _PSC;
X			plen--;
X			}
X		for (; plen > 0; plen--, p1_p2++, p2++)
X			if ((*p1_p2 = *p2) == '\0')
X				break;
X		}
X	if (plen == 0)
X		{
X		*--p1_p2 = '\0';
X		if (*PGN != '\0')
X			fprintf(stderr, "%s: ", PGN);
X		fprintf(stderr, "pathname too long\n");
X		}
X	return(sp1_p2);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/pathcat.c"
fi
if `test ! -s src/pathhead.c`
then
echo "x - src/pathhead.c"
sed 's/^X//' > src/pathhead.c << '@\End\of\File\'
X/* $Header: pathhead.c,v 1.2 85/03/08 17:21:50 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * pathhead() removes tail of pathname and returns pathname. The tail is
X * defined as that part of the pathname after the last separator.
X */
X#include "null.h"
X#include "path.h"
X
Xchar *
Xpathhead(pathname)
X	register char *pathname;
X{
X	register char *ls;		/* last separator character */
X	register char *p;		/* pathname pointer */
X
X	ls = NULL;
X	for (p = pathname; *p != '\0'; p++)
X		if (*p == _PSC)
X			ls = p;
X	if (ls != NULL) *ls = '\0';
X	return(pathname);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/pathhead.c"
fi
if `test ! -s src/pperror.c`
then
echo "x - src/pperror.c"
sed 's/^X//' > src/pperror.c << '@\End\of\File\'
X/* $Header: pperror.c,v 1.1 85/03/14 17:00:12 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * pperror() writes a system error message to standard error output,
X * preceded by the name of the program and message.
X */
X#include <stdio.h>
X
Xpperror(message)
X	char *message;			/* error message */
X{
X	extern char *PGN;		/* program name */
X
X	fprintf(stderr, "%s: ", PGN);
X	perror(message);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/pperror.c"
fi
if `test ! -s src/rule.c`
then
echo "x - src/rule.c"
sed 's/^X//' > src/rule.c << '@\End\of\File\'
X/* $Header: rule.c,v 1.2 85/05/16 12:49:56 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include "Mkmf.h"
X#include "null.h"
X#include "rule.h"
X#include "slist.h"
X#include "suffix.h"
X#include "system.h"
X#include "yesno.h"
X
X#define MAXNAMLEN	255
X
Xstatic RULEBLK *Ruletab[RULETABSIZE];	/* rules table */
Xstatic SLIST *Rulelist = NULL;		/* transformation rule list */
X
X/*
X * buildruletable() converts a list of transformation rules into a hash table
X * for fast lookup. Returns YES if successful, otherwise NO.
X */
Xbuildruletable()
X{
X	extern char *DEFRULE[];		/* default preprocessor rules */
X	int i;				/* default rule list counter */
X	int instalrule();		/* instale rule in hash table */
X	SLBLK *rblk;			/* singly-linked rulename block */
X
X	/* process default rules */
X	for (i = 0; DEFRULE[i] != NULL; i++)
X		{
X		if (instalrule(DEFRULE[i]) == NO)
X			{
X			warn("out of memory");
X			return(NO);
X			}
X		}
X
X	/* process rules found in makefile */
X	if (Rulelist != NULL)
X		{
X		for (rblk = Rulelist->head; rblk != NULL; rblk = rblk->next)
X			{
X			if (instalrule(rblk->key) == NO)
X				{
X				warn("out of memory");
X				return(NO);
X				}
X			}
X		}
X	return(YES);
X}
X
X
X
X/*
X * findrule() searchs a line for a transformation rule. Returns the
X * name of the transformation rule, or NULL if not found.
X */
Xchar *
Xfindrule(rulename, bp)
X	char *rulename;			/* transformation rule buffer */
X	register char *bp;		/* I/O buffer pointer */
X{ 
X	register char *rp;		/* rule name pointer */
X	int dotcount = 0;		/* number of '.'s in rule */
X
X	for (rp = rulename; *bp != ':' && *bp != ' ' && *bp != '\t'; rp++, bp++)
X		{
X		if ((*rp = *bp) == '.')
X			dotcount++;
X		}
X	*rp = '\0';
X
X	/* eat up white space between rule and ':' */
X	if (*bp != ':')
X		{
X		while (*bp == ' ' || *bp == '\t')
X			bp++;
X		if (*bp != ':')
X			return(NULL);
X		}
X
X	return((dotcount == 2) ? rulename : NULL);
X}
X
X
X
X/*
X * instalrule() installs a source transformation rule in the rule lookup
X * table. The rule table consists of a set of singly-linked lists, indexed
X * by the first character of the suffix of the target file. The index of
X * the target file is used by lookuprule() to find out the name of the file
X * from which it was derived. Returns YES if successful, otherwise NO.
X */
Xinstalrule(rule)
X	char *rule;			/* rule to be installed in Rule table */
X{
X	char *malloc();			/* memory allocator */
X	char *rindex();			/* find last occurrence of character */
X	char *strsav();			/* save a string somewhere */
X	char *target;			/* target suffix */
X	int lookupsfx();		/* get suffix type */
X	int ruleindex;			/* index into rule table */
X	RULEBLK *rblk;			/* rule list block */
X
X	target = rindex(rule, '.') + 1;
X	if (lookupsfx(target) == SFXSRC)
X		{
X		ruleindex = target[0];
X		if ((rblk = (RULEBLK *) malloc(sizeof(RULEBLK))) == NULL)
X			return(NO);
X		if ((rblk->r_rule = strsav(rule)) == NULL)
X			return(NO);
X		rblk->r_next = Ruletab[ruleindex];
X		Ruletab[ruleindex] = rblk;
X		}
X	return(YES);
X}
X
X
X
X/*
X * lookuprule() applies successive transformation rules to filename, and
X * checks to see if the file exists. Returns YES if filename exists,
X * otherwise NO.
X */
Xlookuprule(target, source)
X	char *target;			/* name of (transformed) file */
X	char *source;			/* name of source file */
X{
X	register char *r;		/* rule pointer */
X	register char *s;		/* source buffer pointer */
X	char *rindex();			/* find last occurrence of character */
X	char *sourcesuffix;		/* source file suffix */
X	char *strcpy();			/* string copy */
X	char *rulesuffix;		/* target suffix in each rule */
X	char *targetsuffix;		/* transformed file suffix string */
X	int ruleindex;			/* index into rule table */
X	int strcmp();			/* string comparison */
X	RULEBLK *rblk;			/* rule list block */
X
X	if ((targetsuffix = rindex(target, '.')) == NULL)
X		return(NO);
X	ruleindex = targetsuffix[1];
X	if (Ruletab[ruleindex] != NULL)
X		{
X		strcpy(source, target);
X		sourcesuffix = rindex(source, '.');
X		for (rblk=Ruletab[ruleindex]; rblk != NULL; rblk=rblk->r_next)
X			{
X			rulesuffix = rindex(rblk->r_rule, '.');
X			if (strcmp(rulesuffix, targetsuffix) == 0)
X				{
X				r = rblk->r_rule;
X				s = sourcesuffix;
X				while (*++s = *++r)
X					if (*s == '.')
X						{
X						*s = '\0';
X						break;
X						}
X				if (FILEXIST(source))
X					return(YES);
X				}
X			}
X		}
X	return(NO);
X}
X
X
X
X/*
X * storerule() appends a transformation rule to the end of a singly-linked
X * list. Returns integer NO if out of memory, otherwise YES.
X */
Xstorerule(rulename)
X	char *rulename;			/* transformation rule name */
X{
X	char *slappend();		/* append rule to list */
X	SLIST *slinit();		/* initialize transformation list */
X
X	if (Rulelist == NULL)
X		Rulelist = slinit();
X	if (slappend(rulename, Rulelist) == NULL)
X		return(NO);
X	return(YES);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/rule.c"
fi
if `test ! -s src/slappend.c`
then
echo "x - src/slappend.c"
sed 's/^X//' > src/slappend.c << '@\End\of\File\'
X/* $Header: slappend.c,v 1.2 85/03/18 13:18:28 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * slappend() saves a null-terminated key string somewhere and inserts a
X * pointer to the key at the tail of list slist. Returns a pointer to
X * the somewhere, or a null pointer if out of memory.
X */
X#include <stdio.h>
X#include "macro.h"
X#include "null.h"
X#include "slist.h"
X
Xextern char *PGN;			/* program name */
X
Xchar *
Xslappend(key, slist)
X	char *key;			/* key string */
X	SLIST *slist;			/* pointer to list head block */
X{
X	char *malloc();			/* memory allocator */
X	char *strcpy();			/* string copy */
X	int strlen();			/* string length */
X	SLBLK *slbptr;			/* pointer to list block */
X	unsigned int klen;		/* key length */
X
X	if (slist == NULL)
X		return(NULL);
X	klen = strlen(key);
X	slist->maxkey = MAX(slist->maxkey, klen);
X	if ((slbptr = (SLBLK *) malloc(sizeof(SLBLK))) == NULL ||
X	    (slbptr->key = malloc(klen+1)) == NULL)
X		{
X		if (*PGN != '\0')
X			fprintf(stderr, "%s: ", PGN);
X		fprintf(stderr, "out of memory\n");
X		return(NULL);
X		}
X	strcpy(slbptr->key, key);
X	slbptr->next = NULL;
X	if (slist->tail == NULL)
X		slist->head = slist->tail = slbptr;
X	else
X		slist->tail = slist->tail->next = slbptr;
X	slist->nk++;
X	return(slbptr->key);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/slappend.c"
fi
if `test ! -s src/slinit.c`
then
echo "x - src/slinit.c"
sed 's/^X//' > src/slinit.c << '@\End\of\File\'
X/* $Header: slinit.c,v 1.2 85/03/18 13:18:52 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * slinit() returns a pointer to the head block of a new list, or null
X * pointer if out of memory.
X */
X#include <stdio.h>
X#include "null.h"
X#include "slist.h"
X
Xextern char *PGN;			/* program name */
X
XSLIST *
Xslinit()
X{
X	char *malloc();			/* memory allocator */
X	SLIST *slist;			/* pointer to list head block */
X
X	if ((slist = (SLIST *) malloc(sizeof(SLIST))) == NULL)
X		{
X		if (*PGN != '\0')
X			fprintf(stderr, "%s: ", PGN);
X		fprintf(stderr, "out of memory\n");
X		return(NULL);
X		}
X	slist->nk = 0;
X	slist->maxkey = 0;
X	slist->head = slist->curblk = slist->tail = NULL;
X	return(slist);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/slinit.c"
fi
if `test ! -s src/slsort.c`
then
echo "x - src/slsort.c"
sed 's/^X//' > src/slsort.c << '@\End\of\File\'
X/* $Header: slsort.c,v 1.2 85/03/18 13:19:42 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * slsort() sorts list slist according to comparison function compar().
X * compar() is to be called with two arguments and must return an integer
X * greater than, equal to, or less than 0, depending on the lexicographic
X * relationship between the two arguments. Returns integer YES if
X * successful, otherwise NO if out of memory.
X */
X#include <stdio.h>
X#include "null.h"
X#include "slist.h"
X#include "yesno.h"
X
Xextern char *PGN;			/* program name */
X
Xstatic int (*sscmp)();			/* string compare function */
X
Xslsort(compar, slist)
X	int (*compar)();		/* compare two strings */
X	SLIST *slist;			/* pointer to list head block */
X{
X	char **kp;			/* pointer to key pointer array */
X	char *malloc();			/* memory allocator */
X	char **skp;			/* ptr to start of key ptr array */
X	int comparb();			/* compare 2 list blocks */
X	SLBLK *curblk;			/* current list block */
X
X	if (slist->nk <= 0)
X		return(YES);
X	else if ((skp = (char **) malloc((unsigned)slist->nk*sizeof(char *))) == NULL)
X		{
X		if (*PGN != '\0')
X			fprintf(stderr, "%s: ", PGN);
X		fprintf(stderr, "out of memory\n");
X		return(NO);
X		}
X	for (kp = skp, curblk = slist->head; curblk != NULL; kp++, curblk = curblk->next)
X		*kp = curblk->key;
X
X	sscmp = compar;
X	qsort((char *) skp, slist->nk, sizeof(char *), comparb);
X
X	for (kp = skp, curblk = slist->head; curblk != NULL; kp++, curblk = curblk->next)
X		curblk->key = *kp;
X	
X	free((char *) skp);
X	return(YES);
X}
X
X
X
X/*
X * comparb() compares key strings in 2 list blocks. Returns whatever
X * sscmp() returns. sscmp() is a string compare function.
X */
Xstatic int
Xcomparb(s1, s2)
X	char **s1;			/* string pointer */
X	char **s2;			/* string pointer */
X{
X	return(sscmp(*s1, *s2));
X}
@\End\of\File\
else
  echo "shar: Will not over write src/slsort.c"
fi
if `test ! -s src/strpcpy.c`
then
echo "x - src/strpcpy.c"
sed 's/^X//' > src/strpcpy.c << '@\End\of\File\'
X/* $Header: strpcpy.c,v 1.1 85/03/14 17:00:27 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * strpcpy() copies string s2 to s1 and returns a pointer to the
X * next character after s1.
X */
Xchar *
Xstrpcpy(s1, s2)
X	register char *s1;
X	register char *s2;
X{
X	while (*s1++ = *s2++)
X		continue;
X	return(--s1);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/strpcpy.c"
fi
if `test ! -s src/strsav.c`
then
echo "x - src/strsav.c"
sed 's/^X//' > src/strsav.c << '@\End\of\File\'
X/* $Header: strsav.c,v 1.1 85/03/14 17:00:30 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * strsav() saves a string somewhere and returns a pointer to the somewhere.
X * Returns NULL on error.
X */
X#include "null.h"
X
Xchar *
Xstrsav(s)
X	char *s;
X{
X	char *sptr;			/* somewhere string pointer */
X	char *malloc();			/* memory allocator */
X	char *strcpy();			/* string copy */
X	int strlen();			/* string length */
X
X	if ((sptr = malloc((unsigned)(strlen(s)+1))) == NULL)
X		return(NULL);
X	return(strcpy(sptr, s));
X}
@\End\of\File\
else
  echo "shar: Will not over write src/strsav.c"
fi
if `test ! -s src/suffix.c`
then
echo "x - src/suffix.c"
sed 's/^X//' > src/suffix.c << '@\End\of\File\'
X/* $Header: suffix.c,v 1.2 85/03/21 10:19:36 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X#include <stdio.h>
X#include "Mkmf.h"
X#include "hash.h"
X#include "macro.h"
X#include "null.h"
X#include "suffix.h"
X#include "yesno.h"
X
Xstatic int SFX1[SFXTABSIZE];		/* single character suffixes */
Xstatic int INC1[SFXTABSIZE];		/* include file types for 1 char sfx */
Xstatic SFXBLK *SFX2[SFXTABSIZE];	/* 2+ character suffixes */
X
X/*
X * buildsfxtable() converts a suffix list into a hash table for fast lookup.
X * Returns YES if successful, otherwise NO.
X */
Xbuildsfxtable()
X{
X	extern HASH *MDEFTABLE;		/* macro definition table */
X	extern SUFFIX DEFSFX[];		/* default suffix list */
X	HASHBLK *htb;			/* hash table block */
X	HASHBLK *htlookup();		/* find hash table entry */
X	int i;				/* suffix list counter */
X	int installsfx();		/* install suffix in hash table */
X	int sfxbuftotable();		/* feed suffixes to installsfx() */
X
X	/* default suffix list */
X	for (i = 0; DEFSFX[i].suffix != NULL; i++)
X		if (installsfx(DEFSFX[i].suffix, DEFSFX[i].sfxtyp,
X		    DEFSFX[i].inctyp) == NO)
X			return(NO);
X	
X	/* supplementary suffix definitions */
X	if ((htb = htlookup(MSUFFIX, MDEFTABLE)) != NULL)
X		{
X		if (sfxbuftotable(htb->h_def) == NO)
X			return(NO);
X		}
X	return(YES);
X}
X
X
X
X/*
X * installsfx() installs a suffix in one of two suffix tables: SFX1 for
X * one character suffixes, and SFX2 for two or more character suffixes.
X * For a suffix that already exists, only its type and corresponding
X * included file type is updated. Returns integer YES if successful,
X * otherwise NO.
X */
Xinstallsfx(suffix, sfxtyp, inctyp)
X	char *suffix;			/* suffix string */
X	int sfxtyp;			/* suffix type */
X	int inctyp;			/* include file type */
X{
X	char *malloc();			/* memory allocator */
X	char *strsav();			/* save a string somewhere */
X	int sfxindex;			/* index into suffix tables */
X	SFXBLK *sfxblk;			/* suffix list block */
X
X	if (*suffix == '.')
X		suffix++;
X	sfxindex = suffix[0];
X	if (suffix[0] == '\0' || suffix[1] == '\0')
X		{
X		SFX1[sfxindex] = sfxtyp;	/* 0 or 1 character suffix */
X		INC1[sfxindex] = inctyp;
X		}
X	else	{				/* 2+ character suffix */
X		if ((sfxblk = (SFXBLK *) malloc(sizeof(SFXBLK))) == NULL)
X			return(NO);
X		if ((sfxblk->sfx.suffix = strsav(suffix)) == NULL)
X			return(NO);
X		sfxblk->sfx.sfxtyp = sfxtyp;
X		sfxblk->sfx.inctyp = inctyp;
X		sfxblk->next = SFX2[sfxindex];
X		SFX2[sfxindex] = sfxblk;
X		}
X	return(YES);
X}
X
X
X
X/*
X * lookuptypeofinclude() returns the include file type for suffix, or 0 if
X * unknown suffix.
X */
Xlookuptypeofinclude(suffix)
X	char *suffix;			/* suffix string */
X{
X	SFXBLK *sfxblk;			/* suffix block pointer */
X
X	if (suffix[0] == '\0' || suffix[1] == '\0')
X		return(INC1[*suffix]);		/* 0 or 1 char suffix */
X						/* 2+ character suffix */
X	for (sfxblk = SFX2[*suffix]; sfxblk != NULL; sfxblk = sfxblk->next)
X		if (EQUAL(suffix, sfxblk->sfx.suffix))
X			return(sfxblk->sfx.inctyp);
X	return(0);
X}
X
X
X
X/*
X * lookupsfx() returns the suffix type, or 0 if unknown suffix.
X */
Xlookupsfx(suffix)
X	char *suffix;			/* suffix string */
X{
X	SFXBLK *sfxblk;			/* suffix block pointer */
X
X	if (suffix[0] == '\0' || suffix[1] == '\0')
X		return(SFX1[*suffix]);		/* 0 or 1 char suffix */
X						/* 2+ character suffix */
X	for (sfxblk = SFX2[*suffix]; sfxblk != NULL; sfxblk = sfxblk->next)
X		if (EQUAL(suffix, sfxblk->sfx.suffix))
X			return(sfxblk->sfx.sfxtyp);
X	return(0);
X}
X
X
X
X/*
X * sfxbuftotable() parses a buffer containing suffixes and presents them
X * to installsfx() for installation into the appropriate hash table.
X * The suffix type may be altered by attaching a modifier :suffixtype.
X *	:h	--> header file type
X *	:o	--> object file type
X *	:s	--> source file type (default)
X *	:x	--> executable file type
X *	:	--> unknown file type
X * The include file type may be altered by attaching an additional
X * modifier includetype.
X *	C	--> C source code
X *	F	--> Fortran, Ratfor, Efl source code
X *	P	--> Pascal source code
X * If the suffix is object file type, the OBJSFX default object suffix
X * is modified accordingly. Returns YES if successful, otherwise NO.
X */
Xsfxbuftotable(sfxbuf)
X	char *sfxbuf;			/* buffer conatining suffixes */
X{
X	extern char OBJSFX[];		/* object file name suffix */
X	char *gettoken();		/* get next token */
X	char *rindex();			/* find last occurrence of character */
X	char *sfxtyp;			/* suffix type */
X	char *strcpy();			/* string copy */
X	char suffix[SUFFIXSIZE+2];	/* suffix + modifier */
X	int installsfx();		/* install suffix in hash table */
X
X	while ((sfxbuf = gettoken(suffix, sfxbuf)) != NULL)
X		if ((sfxtyp = rindex(suffix, ':')) == NULL)
X			{
X			if (installsfx(suffix, SFXSRC, INCLUDE_NONE) == NO)
X				return(NO);
X			}
X		else	{
X			*sfxtyp = '\0';
X			if (installsfx(suffix, sfxtyp[1], sfxtyp[2]) == NO)
X				return(NO);
X			if (sfxtyp[1] == SFXOBJ)
X				strcpy(OBJSFX, suffix);
X			}
X	return(YES);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/suffix.c"
fi
if `test ! -s src/usage.c`
then
echo "x - src/usage.c"
sed 's/^X//' > src/usage.c << '@\End\of\File\'
X/* $Header: usage.c,v 1.2 85/03/27 07:24:08 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * usage() places a usage error message on the standard error
X * output stream stderr.
X */
X#include <stdio.h>
X#include "null.h"
X
Xextern char *PGN;			/* program name */
X
Xusage(m)
X	char *m;			/* usage error message */
X{
X	fprintf(stderr, "usage: ");
X	if (PGN != NULL && *PGN != '\0')
X		fprintf(stderr, "%s ", PGN);
X	fprintf(stderr, "%s\n", m);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/usage.c"
fi
if `test ! -s src/warn.c`
then
echo "x - src/warn.c"
sed 's/^X//' > src/warn.c << '@\End\of\File\'
X/* $Header: warn.c,v 1.2 85/03/25 12:36:56 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * warn() places an error message on the standard error output stream
X * stderr.
X */
X#include <stdio.h>
X#include "null.h"
X
Xextern char *PGN;			/* program name */
X
Xwarn(m)
X	char *m;			/* warning message */
X{
X	if (PGN != NULL && *PGN != '\0')
X		fprintf(stderr, "%s: ", PGN);
X	fprintf(stderr, "%s\n", m);
X}
@\End\of\File\
else
  echo "shar: Will not over write src/warn.c"
fi
if `test ! -s src/warn2.c`
then
echo "x - src/warn2.c"
sed 's/^X//' > src/warn2.c << '@\End\of\File\'
X/* $Header: warn2.c,v 1.1 85/04/01 17:20:41 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * warn2() places an error message and 2 string arguments on the
X * standard error output stream stderr.
X */
X#include <stdio.h>
X#include "null.h"
X
Xextern char *PGN;			/* program name */
X
Xwarn2(m, s1, s2)
X	char *m;			/* warning message */
X	char *s1;			/* string argument */
X	char *s2;			/* string argument */
X{
X	if (PGN != NULL && *PGN != '\0')
X		fprintf(stderr, "%s: ", PGN);
X	fprintf(stderr, m, s1, s2);
X	fprintf(stderr, "\n");
X}
@\End\of\File\
else
  echo "shar: Will not over write src/warn2.c"
fi
if `test ! -s src/warns.c`
then
echo "x - src/warns.c"
sed 's/^X//' > src/warns.c << '@\End\of\File\'
X/* $Header: warns.c,v 1.1 85/03/25 11:29:43 nicklin Exp $ */
X
X/*
X * Author: Peter J. Nicklin
X */
X
X/*
X * warns() places an error message and a string argument on the
X * standard error output stream stderr.
X */
X#include <stdio.h>
X#include "null.h"
X
Xextern char *PGN;			/* program name */
X
Xwarns(m, s)
X	char *m;			/* warning message */
X	char *s;			/* string argument */
X{
X	if (PGN != NULL && *PGN != '\0')
X		fprintf(stderr, "%s: ", PGN);
X	fprintf(stderr, m, s);
X	fprintf(stderr, "\n");
X}
@\End\of\File\
else
  echo "shar: Will not over write src/warns.c"
fi
if `test ! -s src/Mkmf.h`
then
echo "x - src/Mkmf.h"
sed 's/^X//' > src/Mkmf.h << '@\End\of\File\'
X/* $Header: Mkmf.h,v 1.4 85/04/23 16:43:00 nicklin Exp $ */
X
X/*
X * Mkmf definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Buffer sizes
X */
X#define ANSWERBUFSIZE		256	/* interactive answer buffer size */
X#define INCLUDETABLESIZE	1021	/* include file table size */
X#define MACRODEFSIZE		1024	/* macro definition body size */
X#define MACRONAMSIZE		32	/* macro definition name size */
X#define MDEFTABLESIZE		127	/* macro definition table size */
X#define RULETABSIZE		256	/* rule table size */
X#define SFXTABSIZE		256	/* suffix table size */
X#define SUFFIXSIZE		16	/* suffix size */
X/*
X * Predefined macro names
X */
X#define MCFLAGS		"CFLAGS"
X#define MDESTDIR	"DEST"
X#define MEXTERNALS	"EXTHDRS"
X#define MFFLAGS		"FFLAGS"
X#define MHEADERS	"HDRS"
X#define MLIBLIST	"LIBS"
X#define MLIBRARY	"LIBRARY"
X#define MMAKEFILE	"MAKEFILE"
X#define MMOREINCDIRS	"MOREINCDIRS"
X#define MOBJECTS	"OBJS"
X#define MPFLAGS		"PFLAGS"
X#define MPROGRAM	"PROGRAM"
X#define MSOURCE		"SRCS"
X#define MSUFFIX		"SUFFIX"
X/*
X * Predefined macro values
X */
X#define VERROR		       -1
X#define VUNKNOWN		0
X#define VREADONLY		1
X#define VREADWRITE		2
X#define VLIBRARY		3
X#define VPROGRAM		4
X#define VDESTDIR		5
X/*
X * Include statement styles
X */
X#define INCLUDE_C		'C'	/* #include "file" */
X#define INCLUDE_FORTRAN		'F'	/* include "file" or #include "file" */
X#define INCLUDE_PASCAL		'P'	/* #include "file" */
X#define INCLUDE_NONE		0	/* no include file */
X/*
X * Marker to indicate start of included file dependencies
X */
X#define DEPENDMARK		"###"
@\End\of\File\
else
  echo "shar: Will not over write src/Mkmf.h"
fi
if `test ! -s src/defaultrul.h`
then
echo "x - src/defaultrul.h"
sed 's/^X//' > src/defaultrul.h << '@\End\of\File\'
X".y.c", 	/* Yacc */
X".l.c", 	/* Lex */
@\End\of\File\
else
  echo "shar: Will not over write src/defaultrul.h"
fi
if `test ! -s src/defaultsfx.h`
then
echo "x - src/defaultsfx.h"
sed 's/^X//' > src/defaultsfx.h << '@\End\of\File\'
X".c", SFXSRC, INCLUDE_C,	/* C */
X".e", SFXSRC, INCLUDE_FORTRAN,	/* Efl */
X".F", SFXSRC, INCLUDE_FORTRAN,	/* Fortran */
X".f", SFXSRC, INCLUDE_FORTRAN,	/* Fortran */
X".h", SFXHEAD, INCLUDE_NONE,	/* header */
X".i", SFXHEAD, INCLUDE_NONE,	/* Pascal include */
X".l", SFXSRC, INCLUDE_C,	/* Lex */
X".o", SFXOBJ, INCLUDE_NONE,	/* object */
X".p", SFXSRC, INCLUDE_PASCAL,	/* Pascal */
X".r", SFXSRC, INCLUDE_FORTRAN,	/* Ratfor */
X".s", SFXSRC, INCLUDE_NONE,	/* Assembler */
X".y", SFXSRC, INCLUDE_C,	/* Yacc */
@\End\of\File\
else
  echo "shar: Will not over write src/defaultsfx.h"
fi
if `test ! -s src/dlist.h`
then
echo "x - src/dlist.h"
sed 's/^X//' > src/dlist.h << '@\End\of\File\'
X/* $Header: dlist.h,v 1.1 85/04/23 13:56:24 nicklin Exp $ */
X
X/*
X * Dependency list definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Dependency list block
X */
Xtypedef struct _dlblk
X	{
X	int d_type;			/* source file type */
X	struct slblk *d_src;		/* points to a source list block */
X	struct _iblk *d_incl;		/* pointer to include block chain */
X	struct _dlblk *d_next;		/* ptr to next list block */
X	} DLBLK;
X/*
X * Dependency list head block
X */
Xtypedef struct _dlisthb
X	{
X	DLBLK *d_head;			/* pointer to first list block */
X	DLBLK *d_tail;			/* pointer to last list block */
X	} DLIST;
X/*
X * Functions defined for dependency list operations
X */
Xextern DLBLK *dlappend();		/* append to list */
Xextern DLIST *dlinit();			/* initialize list */
Xextern void dlprint();			/* print list */
@\End\of\File\
else
  echo "shar: Will not over write src/dlist.h"
fi
if `test ! -s src/getarg.h`
then
echo "x - src/getarg.h"
sed 's/^X//' > src/getarg.h << '@\End\of\File\'
X/* $Header: getarg.h,v 1.1 85/03/14 15:32:56 nicklin Exp $ */
X
X/*
X * Get command line argument
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Argument syntax: `-xargument' or `-x argument'
X */
X#define GETARG(p) ((p[1] != '\0') ? ++p : (--argc, *++argv))
X
X/*
X * Argument syntax: `-xargument'
X *
X * #define GETARG(p) (++p)
X */
@\End\of\File\
else
  echo "shar: Will not over write src/getarg.h"
fi
if `test ! -s src/hash.h`
then
echo "x - src/hash.h"
sed 's/^X//' > src/hash.h << '@\End\of\File\'
X/* $Header: hash.h,v 1.2 85/03/26 15:49:56 nicklin Exp $ */
X
X/*
X * Hash table definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Singly-linked list block containing a pointer to a hash table
X * block for an include file
X */
Xtypedef struct _iblk
X	{
X	int i_loop;
X	struct _hblk *i_hblk;
X	struct _iblk *i_next;
X	} INCBLK;
X/*
X * Hash table block
X */
Xtypedef struct _hblk
X	{
X	char *h_key;			/* points to key */
X	char *h_def;			/* points to definition string */
X	int h_val;			/* integer value */
X	struct _iblk *h_sub;		/* ptr to include subchain */
X	struct _hblk *h_tag;		/* ptr to auxiliary tag chain */
X	struct _hblk *h_next;		/* ptr to next block */
X	} HASHBLK;
X/*
X * Hash pointer table struct
X */
Xtypedef struct _hash
X	{
X	HASHBLK **hashtab;		/* hash pointer table */
X	int hashsiz;			/* hash table size */
X	} HASH;
X/*
X * Functions defined for hash tables
X */
Xextern HASHBLK *htbrm();		/* remove hash table block */
Xextern int hthash();			/* compute hash value */
Xextern HASH *htinit();			/* initialize hash table */
Xextern HASHBLK *htinstall();		/* install hash table entry */
Xextern HASHBLK *htlookup();		/* find hash table entry */
Xextern void htrm();			/* remove hash table entry */
@\End\of\File\
else
  echo "shar: Will not over write src/hash.h"
fi
if `test ! -s src/macro.h`
then
echo "x - src/macro.h"
sed 's/^X//' > src/macro.h << '@\End\of\File\'
X/* $Header: macro.h,v 1.2 85/03/19 09:18:02 nicklin Exp $ */
X
X/*
X * General macro function definitions
X *
X * Author: Peter J. Nicklin
X */
X
Xint strcmp();				/* string comparison */
X
X#undef CHDIR
X#define CHDIR(d) \
X	(chdir(d) == 0)			/* change directory */
X
X#undef DOTDIR
X#define DOTDIR(dp) \
X	(dp->d_name[0] == '.' && dp->d_name[1] == '\0')
X					/* current directory? */
X#undef DOTDOTDIR
X#define DOTDOTDIR(dp) \
X	(dp->d_name[0] == '.' && dp->d_name[1] == '.' && dp->d_name[2] == '\0')
X					/* parent directory? */
X#undef EQUAL
X#define EQUAL(s1,s2) \
X	(strcmp(s1,s2) == 0)		/* string comparison */
X
X#undef MIN
X#define MIN(a,b) \
X	(((a) < (b)) ? (a) : (b))	/* minimum of two values */
X
X#undef MAX
X#define MAX(a,b) \
X	(((a) > (b)) ? (a) : (b))	/* maximum of two values */
X
X#undef WHITESPACE
X#define WHITESPACE(c) \
X	(c == ' ' || c == '\t')		/* unseen space in a file */
@\End\of\File\
else
  echo "shar: Will not over write src/macro.h"
fi
if `test ! -s src/null.h`
then
echo "x - src/null.h"
sed 's/^X//' > src/null.h << '@\End\of\File\'
X/* $Header: null.h,v 1.1 85/03/14 15:33:08 nicklin Exp $ */
X
X/*
X * NULL constant definition
X *
X * Author: Peter J. Nicklin
X */
X
X#define CNULL		(char *) 0
X#ifndef NULL
X#define NULL		0
X#endif
@\End\of\File\
else
  echo "shar: Will not over write src/null.h"
fi
if `test ! -s src/path.h`
then
echo "x - src/path.h"
sed 's/^X//' > src/path.h << '@\End\of\File\'
X/* $Header: path.h,v 1.1 85/03/14 15:33:11 nicklin Exp $ */
X
X/*
X * Pathname definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Buffer sizes
X */
X#define ALIASSIZE	30		/* project directory alias size */
X#define TYPESIZE	30		/* project directory type label size */
X#define DIRDESCSIZE	128		/* project directory description size */
X#define P_BUFSIZE	1024		/* pathname buffer size */
X#define	PATHSIZE	256		/* maximum pathname length */
X#define PPATHSIZE	128		/* maximum project pathname length */
X#define TYPBUFSIZE	256		/* directory type labels buffer */
X
X/* 
X * Nomenclature (WARNING: Check definition usage BEFORE changing)
X */
X#define _CDIRC		'.'		/* current directory character */
X#define _HDIRC		'~'		/* home directory character */
X#define _PDIRC		'^'		/* project root directory character */
X#define _PDTSC		'/'		/* project dir type labels sep char */
X#define _PPSC		'^'		/* project path separator character */
X#define _PSC		'/'		/* pathname separator character */
X#define _RDIRC		'/'		/* root directory character */
X#define CURDIR		"."		/* current directory */
X#define PARENTDIR	".."		/* parent directory */
X#define PATHSEP		"/"		/* pathname separator */
X#define PPATHSEP	"^"		/* project pathname separator */
X#define ROOTDIR		"/"		/* root directory */
X#define ROOTPROJECT	"^"		/* root project */
X#define USERPROJECT	"~"		/* user's root project */
X
X/*
X * Pathname types
X */
X#define P_IFMT		0xf0000		/* project pathname mask */
X#define	P_IFNEW		0x00000		/* new directory or file */
X#define P_IFREG		0x10000		/* regular directory or file */
X#define	P_IFHOME	0x20000		/* root project root directory */
X#define P_IFPDIR	0x30000		/* project directory */
X#define	P_IFPROOT	0x40000		/* project root directory */
X
X/*
X * Pathname struct
X */
Xtypedef struct _path
X	{
X	unsigned long p_mode;		/* type of pathname */
X	char *p_alias;			/* pathname alias */
X	char *p_path;			/* pathname */
X	char *p_type;			/* project directory type labels */
X	char *p_desc;			/* project directory description */
X	char p_buf[P_BUFSIZE];		/* pathname buffer */
X	char p_project[PATHSIZE];	/* pathname's project */
X	} PATH;
@\End\of\File\
else
  echo "shar: Will not over write src/path.h"
fi
if `test ! -s src/rule.h`
then
echo "x - src/rule.h"
sed 's/^X//' > src/rule.h << '@\End\of\File\'
X/* $Header: rule.h,v 1.1 85/05/02 08:01:11 nicklin Exp $ */
X
X/*
X * Rule definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Rule table block struct
X */
Xtypedef struct _ruleblk
X	{
X	char *r_rule;			/* pointer to rule string */
X	struct _ruleblk *r_next;	/* ptr to next rule list block */
X	} RULEBLK;
@\End\of\File\
else
  echo "shar: Will not over write src/rule.h"
fi
if `test ! -s src/sccsid.h`
then
echo "x - src/sccsid.h"
sed 's/^X//' > src/sccsid.h << '@\End\of\File\'
X/* $Header: sccsid.h,v 1.1 85/05/17 08:53:55 nicklin Exp $ */
X
X/*
X * Release identification
X *
X * Author: Peter J. Nicklin
X */
Xstatic char *sccsid = "@(#)V4BSDRel2";
@\End\of\File\
else
  echo "shar: Will not over write src/sccsid.h"
fi
if `test ! -s src/slist.h`
then
echo "x - src/slist.h"
sed 's/^X//' > src/slist.h << '@\End\of\File\'
X/* $Header: slist.h,v 1.1 85/03/14 15:33:33 nicklin Exp $ */
X
X/*
X * Singly-linked list definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Singly-linked list macros
X */
X#define SLNUM(slist)	(slist)->nk
X/*
X * Singly-linked list block
X */
Xtypedef struct slblk
X	{
X	char *key;			/* points to a key */
X	struct slblk *next;		/* ptr to next list block */
X	} SLBLK;
X/*
X * Singly-linked list head block
X */
Xtypedef struct slisthb
X	{
X	int nk;				/* number of keys in list */
X	int maxkey;			/* length of longest key */
X	SLBLK *head;			/* pointer to first list block */
X	SLBLK *curblk;			/* pointer to current block */
X	SLBLK *tail;			/* pointer to last list block */
X	} SLIST;
X/*
X * Functions defined for singly-linked list operations
X */
Xextern char *slappend();		/* append key */
Xextern char *slget();			/* get next key */
Xextern SLIST *slinit();			/* initialize list */
Xextern char *slinsert();		/* insert key */
Xextern int slpop();			/* pop key */
Xextern char *slprepend();		/* prepend key */
Xextern void slprint();			/* print list */
Xextern void slrewind();			/* rewind list */
Xextern void slrm();			/* remove list item */
Xextern int slsort();			/* sort list */
Xextern void slsplice();			/* splice two lists */
@\End\of\File\
else
  echo "shar: Will not over write src/slist.h"
fi
if `test ! -s src/spms.h`
then
echo "x - src/spms.h"
sed 's/^X//' > src/spms.h << '@\End\of\File\'
X/* $Header: spms.h,v 1.1 85/03/14 15:33:41 nicklin Exp $ */
X
X/*
X * SPMS definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Nomenclature
X */
X#define CURPROJECT	"..."		/* current project root directory */
X#define PARENTPROJECT	"...."		/* parent project root directory */
X#define PROJECTLOG	"projectlog"	/* log-file in project root dir */
X#define PROJECTRC	".projectrc"	/* project environment file */
X#define SPMSBIN		"/usr/new"	/* SPMS binaries */
X#define SPMSLIB		"/usr/new/lib"	/* SPMS data files */
X#define SPMSROOT	"/usr/new"	/* SPMS root directory */
@\End\of\File\
else
  echo "shar: Will not over write src/spms.h"
fi
if `test ! -s src/suffix.h`
then
echo "x - src/suffix.h"
sed 's/^X//' > src/suffix.h << '@\End\of\File\'
X/* $Header: suffix.h,v 1.1 85/03/14 15:38:45 nicklin Exp $ */
X
X/*
X * Suffix definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Suffix types 
X */
X#define SFXHEAD			'h'	/* header file name suffix */
X#define SFXOBJ			'o'	/* object file name suffix */
X#define SFXOUT			'x'	/* executable file name suffix */
X#define SFXSRC			's'	/* source file name suffix */
X
X/*
X * Suffix table structs
X */
Xtypedef struct _suffix
X	{
X	char *suffix;			/* points to a suffix */
X	int sfxtyp;			/* type of file name suffix */
X	int inctyp;			/* type of included file */
X	} SUFFIX;
X
Xtypedef struct _sfxblk
X	{
X	SUFFIX sfx;			/* suffix struct */
X	struct _sfxblk *next;		/* ptr to next suffix list block */
X	} SFXBLK;
@\End\of\File\
else
  echo "shar: Will not over write src/suffix.h"
fi
if `test ! -s src/system.h`
then
echo "x - src/system.h"
sed 's/^X//' > src/system.h << '@\End\of\File\'
X/* $Header: system.h,v 1.5 85/06/27 12:10:18 nicklin Exp $ */
X
X/*
X * System-dependent definitions
X *
X * Author: Peter J. Nicklin
X */
X#define FILEXIST(file)		(access(file,0) ? 0 : 1)
X#define FILEWRITE(file)		(access(file,6) ? 0 : 1)
X
X#ifdef V4BSD
X#include <sys/file.h>
X#define CREATE(name,flags,mode)	open(name,flags|FCREAT,mode)
X#define FORK()			vfork()
X#define OPEN(name,flags,mode)	open(name,flags,mode)
X#define RENAME(from,to)		rename(from,to)
X#else
X#define NBBY 8            
X#define O_RDONLY		000
X#define O_WRONLY		001
X#define O_RDWR			002
X#define CREATE(name,flags,mode)	creat(name,mode)
X#define FORK()			fork()
X#define OPEN(name,flags,mode)	open(name,flags)
X#define RENAME(from,to)		unlink(to); link(from,to); unlink(from)
X#endif
@\End\of\File\
else
  echo "shar: Will not over write src/system.h"
fi
if `test ! -s src/target.h`
then
echo "x - src/target.h"
sed 's/^X//' > src/target.h << '@\End\of\File\'
X/* $Header: target.h,v 1.1 85/03/14 15:38:49 nicklin Exp $ */
X
X/*
X * Target definitions
X *
X * Author: Peter J. Nicklin
X */
X
X/*
X * Target struct
X */
Xtypedef struct _target
X	{
X	int type;			/* prog, lib, or other target type */
X	int dest;			/* target destination flag */
X	} TARGET;
@\End\of\File\
else
  echo "shar: Will not over write src/target.h"
fi
if `test ! -s src/yesno.h`
then
echo "x - src/yesno.h"
sed 's/^X//' > src/yesno.h << '@\End\of\File\'
X/* $Header: yesno.h,v 1.1 85/03/14 15:34:01 nicklin Exp $ */
X
X/*
X * YES/NO constant definitions
X *
X * Author: Peter J. Nicklin
X */
X
X#define YES 1
X#define NO  0
@\End\of\File\
else
  echo "shar: Will not over write src/yesno.h"
fi
if `test ! -s src/oMakefile`
then
echo "x - src/oMakefile"
sed 's/^X//' > src/oMakefile << '@\End\of\File\'
X# $Header: Makefile,v 1.1 84/09/14 15:37:40 nicklin Exp $
X#
XCFLAGS	      = -D$(VERSION) -O
X
XHOMEDIR	      = /usr4/texers/jwm
X
XDEST	      = $(HOMEDIR)/bin
X
XEXTHDRS	      =
X
XHDRS	      = Mkmf.h \
X		defaultrul.h \
X		defaultsfx.h \
X		dlist.h \
X		getarg.h \
X		hash.h \
X		macro.h \
X		null.h \
X		path.h \
X		rule.h \
X		sccsid.h \
X		slist.h \
X		spms.h \
X		suffix.h \
X		system.h \
X		target.h \
X		yesno.h
X
XLDFLAGS	      =
X
XLIBS	      =
X
XLINKER	      = cc
X
XLINTFLAGS     = -D$(VERSION)
X
XLINTLIST      = -lc
X
XMAKEFILE      = Makefile
X
XOBJS	      = Mkmf.o \
X		badopt.o \
X		buildlist.o \
X		depend.o \
X		dlist.o \
X		editmf.o \
X		getcwp.o \
X		getproject.o \
X		hash.o \
X		iolin.o \
X		macro.o \
X		misc.o \
X		mustfopen.o \
X		optpath.o \
X		pathcat.o \
X		pathhead.o \
X		pperror.o \
X		rule.o \
X		slappend.o \
X		slinit.o \
X		slsort.o \
X		strpcpy.o \
X		strsav.o \
X		suffix.o \
X		usage.o \
X		warn.o \
X		warn2.o \
X		warns.o
X
XPRINT	      = pr
X
XPROGRAM	      = mkmf
X
XSRCS	      = Mkmf.c \
X		badopt.c \
X		buildlist.c \
X		depend.c \
X		dlist.c \
X		editmf.c \
X		getcwp.c \
X		getproject.c \
X		hash.c \
X		iolin.c \
X		macro.c \
X		misc.c \
X		mustfopen.c \
X		optpath.c \
X		pathcat.c \
X		pathhead.c \
X		pperror.c \
X		rule.c \
X		slappend.c \
X		slinit.c \
X		slsort.c \
X		strpcpy.c \
X		strsav.c \
X		suffix.c \
X		usage.c \
X		warn.c \
X		warn2.c \
X		warns.c
X
XVERSION	      = V4BSD
X
Xall:		$(PROGRAM)
X
X$(PROGRAM):     $(OBJS) $(LIBS)
X		@echo -n "Loading $(PROGRAM) ... "
X		@$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
X		@echo "done"
X
Xclean:;		@rm -f $(OBJS)
X
Xco:;		@co -r$(VERSION) $(HDRS) $(SRCS)
X
Xdepend:;	@mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) \
X		'DEST=$$(HOMEDIR)/bin' HOMEDIR=`echo $$HOME`
X
Xdiff:;		@rcsdiff -r$(VERSION) $(HDRS) $(SRCS)
X
Xindex:;		@ctags -wx $(HDRS) $(SRCS)
X
Xinstall:	$(PROGRAM)
X		@echo Installing $(PROGRAM) in $(DEST)
X		@install $(IFLAGS) $(PROGRAM) $(DEST)
X		
X
Xlint:;	        @lint $(LINTFLAGS) $(SRCS) $(LINTLIST)
X
Xprint:;		@$(PRINT) $(HDRS) $(SRCS)
X
Xprogram:        $(PROGRAM)
X
Xtags:           $(HDRS) $(SRCS); @ctags $(HDRS) $(SRCS)
X
Xupdate:		$(DEST)/$(PROGRAM)
X
X$(DEST)/$(PROGRAM): $(SRCS) $(LIBS) $(HDRS) $(EXTHDRS)
X		@make -f $(MAKEFILE) DEST=$(DEST) install tags
X###
XMkmf.o: sccsid.h Mkmf.h getarg.h hash.h null.h path.h target.h slist.h \
X	suffix.h system.h yesno.h defaultrul.h defaultsfx.h
Xbadopt.o: null.h
Xbuildlist.o: Mkmf.h hash.h null.h path.h slist.h suffix.h system.h yesno.h
Xdepend.o: Mkmf.h dlist.h hash.h macro.h null.h path.h slist.h system.h \
X	yesno.h
Xdlist.o: Mkmf.h dlist.h hash.h null.h slist.h yesno.h
Xeditmf.o: Mkmf.h dlist.h hash.h macro.h null.h slist.h system.h yesno.h
Xgetcwp.o: null.h
Xgetproject.o: null.h
Xhash.o: null.h hash.h macro.h
Xiolin.o: yesno.h
Xmacro.o: Mkmf.h hash.h macro.h null.h slist.h yesno.h
Xmisc.o: Mkmf.h hash.h macro.h null.h path.h target.h spms.h suffix.h \
X	system.h yesno.h
Xoptpath.o: path.h
Xpathcat.o: path.h
Xpathhead.o: null.h path.h
Xrule.o: Mkmf.h null.h rule.h slist.h suffix.h system.h yesno.h
Xslappend.o: macro.h null.h slist.h
Xslinit.o: null.h slist.h
Xslsort.o: null.h slist.h yesno.h
Xstrsav.o: null.h
Xsuffix.o: Mkmf.h hash.h macro.h null.h suffix.h yesno.h
Xusage.o: null.h
Xwarn.o: null.h
Xwarn2.o: null.h
Xwarns.o: null.h
@\End\of\File\
else
  echo "shar: Will not over write src/oMakefile"
fi
if `test ! -d x.Makefile`
then
  mkdir x.Makefile
  echo "mkdir x.Makefile"
fi
if `test ! -s x.Makefile/t.Makefile`
then
echo "x - x.Makefile/t.Makefile"
sed 's/^X//' > x.Makefile/t.Makefile << '@\End\of\File\'
XLDFLAGS	      =
X
XLIBS	      =
X
XLINKER	      = cc
X
XOBJS	      =
X
XPROGRAM	      =
X
X$(PROGRAM):     $(OBJS) $(LIBS)
X		$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
@\End\of\File\
else
  echo "shar: Will not over write x.Makefile/t.Makefile"
fi
if `test ! -s x.Makefile/Makefile`
then
echo "x - x.Makefile/Makefile"
sed 's/^X//' > x.Makefile/Makefile << '@\End\of\File\'
X# $Header: Makefile,v 1.1 85/03/14 15:59:05 nicklin Exp $
X#
X#DEST	      = $(DESTDIR)/usr/new/lib
XDEST	      = $(DESTDIR)/lib
X
XMAKEFILE      = Makefile
X
XPRINT	      = pr
X
XPROGRAM	      = p.Makefile
X
XSRCS	      = l.Makefile \
X		p.Makefile \
X		t.Makefile
X
XSUFFIX	      = .Makefile:s
X
XVERSION	      = V4BSD
X
Xall:;
X
Xclean:;
X
Xco:;		@co -r$(VERSION) $(SRCS)
X
Xdepend:;
X
Xdiff:;		@rcsdiff -r$(VERSION) $(HDRS) $(SRCS)
X
Xindex:;
X
Xinstall:	$(SRCS)
X		@echo Installing $(SRCS) in $(DEST)
X		@cp $(SRCS) $(DEST)
X
Xlint:;
X
Xprint:;		@$(PRINT) $(SRCS)
X
Xtags:;
X
Xupdate:		$(DEST)/$(PROGRAM)
X
X$(DEST)/$(PROGRAM): $(SRCS)
X		@make -f $(MAKEFILE) DEST=$(DEST) install tags
X###
@\End\of\File\
else
  echo "shar: Will not over write x.Makefile/Makefile"
fi
if `test ! -s x.Makefile/l.Makefile`
then
echo "x - x.Makefile/l.Makefile"
sed 's/^X//' > x.Makefile/l.Makefile << '@\End\of\File\'
XCFLAGS        = -O
X
XDEST	      = .
X
XEXTHDRS	      =
X
XHDRS	      =
X
XLIBRARY	      = lib.a
X
XMAKEFILE      = Makefile
X
XOBJS	      =
X
XPRINT	      = pr
X
XSRCS	      =
X
Xall:		$(LIBRARY)
X
X$(LIBRARY):	$(OBJS)
X		ar cru $(LIBRARY) $(OBJS)
X		ranlib $(LIBRARY)
X
Xclean:;		rm -f $(OBJS)
X
Xdepend:;	mkmf -f $(MAKEFILE) LIBRARY=$(LIBRARY) DEST=$(DEST)
X
Xextract:;	ar xo $(DEST)/$(LIBRARY)
X		@rm -f __.SYMDEF
X
Xindex:;		ctags -wx $(HDRS) $(SRCS)
X
Xinstall:	$(LIBRARY)
X		install $(LIBRARY) $(DEST)
X		ranlib $(DEST)/$(LIBRARY)
X
Xlibrary:        $(LIBRARY)
X
Xprint:;		$(PRINT) $(HDRS) $(SRCS)
X
Xtags:           $(HDRS) $(SRCS); ctags $(HDRS) $(SRCS)
X
Xupdate:         $(DEST)/$(LIBRARY)
X
X$(DEST)/$(LIBRARY): $(SRCS) $(HDRS) $(EXTHDRS)
X		@-ar xo $(DEST)/$(LIBRARY)
X		@make -f $(MAKEFILE) DEST=$(DEST) install clean
@\End\of\File\
else
  echo "shar: Will not over write x.Makefile/l.Makefile"
fi
if `test ! -s x.Makefile/p.Makefile`
then
echo "x - x.Makefile/p.Makefile"
sed 's/^X//' > x.Makefile/p.Makefile << '@\End\of\File\'
XCFLAGS        = -O
X
XDEST	      = ${HOME}/bin
X
XEXTHDRS	      =
X
XHDRS	      =
X
XLDFLAGS	      =
X
XLIBS	      =
X
XLINKER	      = cc
X
XMAKEFILE      = Makefile
X
XOBJS	      =
X
XPRINT	      = pr
X
XPROGRAM	      = a.out
X
XSRCS	      =
X
Xall:		$(PROGRAM)
X
X$(PROGRAM):     $(OBJS) $(LIBS)
X		$(LINKER) $(LDFLAGS) $(OBJS) $(LIBS) -o $(PROGRAM)
X
Xclean:;		rm -f $(OBJS)
X
Xdepend:;	mkmf -f $(MAKEFILE) PROGRAM=$(PROGRAM) DEST=$(DEST)
X
Xindex:;		ctags -wx $(HDRS) $(SRCS)
X
Xinstall:	$(PROGRAM)
X		install -s $(PROGRAM) $(DEST)
X
Xprint:;		$(PRINT) $(HDRS) $(SRCS)
X
Xprogram:        $(PROGRAM)
X
Xtags:           $(HDRS) $(SRCS); ctags $(HDRS) $(SRCS)
X
Xupdate:		$(DEST)/$(PROGRAM)
X
X$(DEST)/$(PROGRAM): $(SRCS) $(LIBS) $(HDRS) $(EXTHDRS)
X		@make -f $(MAKEFILE) DEST=$(DEST) install
@\End\of\File\
else
  echo "shar: Will not over write x.Makefile/p.Makefile"
fi
echo "Finished archive 2 of 2"
# to concatenate archives, remove anything after this line
exit 0