Path: utzoo!mnetor!uunet!husc6!rutgers!clyde!cbosgd!mandrill!hal!ncoast!allbery From: ljz@fxgrp.UUCP (Lloyd Zusman) Newsgroups: comp.sources.misc Subject: "mkmf" makefile maker (1 of 2) Message-ID: <6903@ncoast.UUCP> Date: 26 Dec 87 02:39:25 GMT Sender: allbery@ncoast.UUCP Lines: 2291 Approved: allbery@ncoast.UUCP X-Archive: comp.sources.misc/mkmf/1 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 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 X#include X#include X#include 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 X#include 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 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