usr.bin/make: Remove legacy make files
authorJohn Marino <draco@marino.st>
Sun, 28 Oct 2012 13:27:26 +0000 (14:27 +0100)
committerJohn Marino <draco@marino.st>
Sun, 28 Oct 2012 13:32:45 +0000 (14:32 +0100)
usr.bin/make has been replaced with usr.bin/bmake, retaining the program
name "make".  usr.bin/make was previously disconnected from the build,
so these files were not longer used.

79 files changed:
usr.bin/make/GNode.h [deleted file]
usr.bin/make/Makefile [deleted file]
usr.bin/make/Makefile.dist [deleted file]
usr.bin/make/PSD.doc/stubs [deleted file]
usr.bin/make/PSD.doc/tutorial.ms [deleted file]
usr.bin/make/arch.c [deleted file]
usr.bin/make/arch.h [deleted file]
usr.bin/make/buf.c [deleted file]
usr.bin/make/buf.h [deleted file]
usr.bin/make/cond.c [deleted file]
usr.bin/make/cond.h [deleted file]
usr.bin/make/config.h [deleted file]
usr.bin/make/dir.c [deleted file]
usr.bin/make/dir.h [deleted file]
usr.bin/make/for.c [deleted file]
usr.bin/make/for.h [deleted file]
usr.bin/make/globals.h [deleted file]
usr.bin/make/hash.c [deleted file]
usr.bin/make/hash.h [deleted file]
usr.bin/make/hash_tables.c [deleted file]
usr.bin/make/hash_tables.h [deleted file]
usr.bin/make/job.c [deleted file]
usr.bin/make/job.h [deleted file]
usr.bin/make/lst.c [deleted file]
usr.bin/make/lst.h [deleted file]
usr.bin/make/main.c [deleted file]
usr.bin/make/make.1 [deleted file]
usr.bin/make/make.c [deleted file]
usr.bin/make/make.h [deleted file]
usr.bin/make/parse.c [deleted file]
usr.bin/make/parse.h [deleted file]
usr.bin/make/pathnames.h [deleted file]
usr.bin/make/proc.c [deleted file]
usr.bin/make/proc.h [deleted file]
usr.bin/make/shell.c [deleted file]
usr.bin/make/shell.h [deleted file]
usr.bin/make/str.c [deleted file]
usr.bin/make/str.h [deleted file]
usr.bin/make/suff.c [deleted file]
usr.bin/make/suff.h [deleted file]
usr.bin/make/targ.c [deleted file]
usr.bin/make/targ.h [deleted file]
usr.bin/make/tests/README [deleted file]
usr.bin/make/tests/basic/t0/expected.status [deleted file]
usr.bin/make/tests/basic/t0/expected.stderr [deleted file]
usr.bin/make/tests/basic/t0/expected.stdout [deleted file]
usr.bin/make/tests/basic/t0/test.sh [deleted file]
usr.bin/make/tests/basic/t1/expected.status [deleted file]
usr.bin/make/tests/basic/t1/expected.stderr [deleted file]
usr.bin/make/tests/basic/t1/expected.stdout [deleted file]
usr.bin/make/tests/basic/t1/test.sh [deleted file]
usr.bin/make/tests/basic/t2/expected.status [deleted file]
usr.bin/make/tests/basic/t2/expected.stderr [deleted file]
usr.bin/make/tests/basic/t2/expected.stdout [deleted file]
usr.bin/make/tests/basic/t2/test.sh [deleted file]
usr.bin/make/tests/basic/t3/expected.status [deleted file]
usr.bin/make/tests/basic/t3/expected.stderr [deleted file]
usr.bin/make/tests/basic/t3/expected.stdout [deleted file]
usr.bin/make/tests/basic/t3/test.sh [deleted file]
usr.bin/make/tests/basic/test.sh [deleted file]
usr.bin/make/tests/common.sh [deleted file]
usr.bin/make/tests/test.sh [deleted file]
usr.bin/make/tests/variables/t0/expected.status [deleted file]
usr.bin/make/tests/variables/t0/expected.stderr [deleted file]
usr.bin/make/tests/variables/t0/expected.stdout [deleted file]
usr.bin/make/tests/variables/t0/test.sh [deleted file]
usr.bin/make/tests/variables/t1/expected.status [deleted file]
usr.bin/make/tests/variables/t1/expected.stderr [deleted file]
usr.bin/make/tests/variables/t1/expected.stdout [deleted file]
usr.bin/make/tests/variables/t1/test.sh [deleted file]
usr.bin/make/tests/variables/t2/expected.status [deleted file]
usr.bin/make/tests/variables/t2/expected.stderr [deleted file]
usr.bin/make/tests/variables/t2/expected.stdout [deleted file]
usr.bin/make/tests/variables/t2/test.sh [deleted file]
usr.bin/make/tests/variables/test.sh [deleted file]
usr.bin/make/util.c [deleted file]
usr.bin/make/util.h [deleted file]
usr.bin/make/var.c [deleted file]
usr.bin/make/var.h [deleted file]

diff --git a/usr.bin/make/GNode.h b/usr.bin/make/GNode.h
deleted file mode 100644 (file)
index 0a7b570..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*-
- * Copyright (c) 1988, 1989, 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- * Copyright (c) 1989 by Berkeley Softworks
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Adam de Boor.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $DragonFly: src/usr.bin/make/GNode.h,v 1.8 2005/08/03 19:48:44 okumoto Exp $
- */
-
-#ifndef GNode_h_39503bf2
-#define        GNode_h_39503bf2
-
-#include <stdbool.h>
-
-#include "lst.h"
-
-struct Suff;
-
-/*
- * The structure for an individual graph node. Each node has several
- * pieces of data associated with it.
- */
-typedef struct GNode {
-       char    *name;  /* The target's name */
-       char    *path;  /* The full pathname of the target file */
-
-       /*
-        * The type of operator used to define the sources (qv. parse.c)
-        *
-        * The OP_ constants are used when parsing a dependency line as a way of
-        * communicating to other parts of the program the way in which a target
-        * should be made. These constants are bitwise-OR'ed together and
-        * placed in the 'type' field of each node. Any node that has
-        * a 'type' field which satisfies the OP_NOP function was never never on
-        * the lefthand side of an operator, though it may have been on the
-        * righthand side...
-        */
-       int     type;
-#define        OP_DEPENDS      0x00000001      /* Execution of commands depends on
-                                        * kids (:) */
-#define        OP_FORCE        0x00000002      /* Always execute commands (!) */
-#define        OP_DOUBLEDEP    0x00000004      /* Execution of commands depends on
-                                        * kids per line (::) */
-#define        OP_OPMASK       (OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP)
-
-#define        OP_OPTIONAL     0x00000008      /* Don't care if the target doesn't
-                                        * exist and can't be created */
-#define        OP_USE          0x00000010      /*
-                                        * Use associated commands for
-                                        * parents
-                                        */
-#define        OP_EXEC         0x00000020      /* Target is never out of date, but
-                                        * always execute commands anyway.
-                                        * Its time doesn't matter, so it has
-                                        * none...sort of
-                                        */
-#define        OP_IGNORE       0x00000040      /*
-                                        * Ignore errors when creating the node
-                                        */
-#define        OP_PRECIOUS     0x00000080      /* Don't remove the target when
-                                        * interrupted */
-#define        OP_SILENT       0x00000100      /* Don't echo commands when executed */
-#define        OP_MAKE         0x00000200      /*
-                                        * Target is a recurrsive make so its
-                                        * commands should always be executed
-                                        * when it is out of date, regardless
-                                        * of the state of the -n or -t flags
-                                        */
-#define        OP_JOIN         0x00000400      /* Target is out-of-date only if any of
-                                        * its children was out-of-date */
-#define        OP_INVISIBLE    0x00004000      /* The node is invisible to its parents.
-                                        * I.e. it doesn't show up in the
-                                        * parents's local variables. */
-#define        OP_NOTMAIN      0x00008000      /* The node is exempt from normal 'main
-                                        * target' processing in parse.c */
-#define        OP_PHONY        0x00010000      /* Not a file target; run always */
-/* Attributes applied by PMake */
-#define        OP_TRANSFORM    0x80000000      /* The node is a transformation rule */
-#define        OP_MEMBER       0x40000000      /* Target is a member of an archive */
-#define        OP_LIB          0x20000000      /* Target is a library */
-#define        OP_ARCHV        0x10000000      /* Target is an archive construct */
-#define        OP_HAS_COMMANDS 0x08000000      /* Target has all the commands it
-                                        * should.  Used when parsing to catch
-                                        * multiple commands for a target */
-#define        OP_SAVE_CMDS    0x04000000      /* Saving commands on .END (Compat) */
-#define        OP_DEPS_FOUND   0x02000000      /* Already processed by Suff_FindDeps */
-
-/*
- * OP_NOP will return true if the node with the given type was not the
- * object of a dependency operator
- */
-#define        OP_NOP(t)       (((t) & OP_OPMASK) == 0x00000000)
-
-       int     order;  /* Its wait weight */
-
-       bool    make;   /* true if this target needs to be remade */
-
-       /* Set to reflect the state of processing on this node */
-       enum {
-               UNMADE,         /* Not examined yet */
-
-               /*
-                * Target is already being made. Indicates a cycle in the graph.
-                * (compat mode only)
-                */
-               BEINGMADE,
-
-               MADE,           /* Was out-of-date and has been made */
-               UPTODATE,       /* Was already up-to-date */
-
-               /*
-                * An error occured while it was being
-                * made (used only in compat mode)
-                */
-               ERROR,
-
-               /*
-                * The target was aborted due to an
-                * error making an inferior (compat).
-                */
-               ABORTED,
-
-               /*
-                * Marked as potentially being part of a graph cycle.  If we
-                * come back to a node marked this way, it is printed and
-                * 'made' is changed to ENDCYCLE.
-                */
-               CYCLE,
-
-               /*
-                * The cycle has been completely printed.  Go back and
-                * unmark all its members.
-                */
-               ENDCYCLE
-       } made;
-
-       /* true if one of this target's children was made */
-       bool    childMade;
-
-       int     unmade;         /* The number of unmade children */
-       int     mtime;          /* Its modification time */
-       int     cmtime;         /* Modification time of its youngest child */
-
-       /*
-        * Links to parents for which this is an implied source, if any. (nodes
-        * that depend on this, as gleaned from the transformation rules.
-        */
-       Lst     iParents;
-
-       /* List of nodes of the same name created by the :: operator */
-       Lst     cohorts;
-
-       /* Lst of nodes for which this is a source (that depend on this one) */
-       Lst     parents;
-
-       /* List of nodes on which this depends */
-       Lst     children;
-
-       /*
-        * List of nodes that must be made (if they're made) after this node is,
-        * but that do not depend on this node, in the normal sense.
-        */
-       Lst     successors;
-
-       /*
-        * List of nodes that must be made (if they're made) before this node
-        * can be, but that do no enter into the datedness of this node.
-        */
-       Lst     preds;
-
-       /*
-        * List of ``local'' variables that are specific to this target
-        * and this target only (qv. var.c [$@ $< $?, etc.])
-        */
-       Lst     context;
-
-       /*
-        * List of strings that are commands to be given to a shell
-        * to create this target.
-        */
-       Lst     commands;
-
-       /* current command executing in compat mode */
-       LstNode *compat_command;
-
-       /*
-        * Suffix for the node (determined by Suff_FindDeps and opaque to
-        * everyone but the Suff module)
-        */
-       struct Suff     *suffix;
-} GNode;
-
-#endif /* GNode_h_39503bf2 */
diff --git a/usr.bin/make/Makefile b/usr.bin/make/Makefile
deleted file mode 100644 (file)
index 6d92d48..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-.INTERRUPT:
-       echo Hey that hurt!
-#      @(#)Makefile    5.2 (Berkeley) 12/28/90
-# $FreeBSD: src/usr.bin/make/Makefile,v 1.13.2.1 2001/05/25 08:33:40 sobomax Exp $
-
-PROG=  make
-CFLAGS+=-I${.CURDIR}
-SRCS=  arch.c buf.c cond.c dir.c for.c hash.c hash_tables.c job.c      \
-       lst.c main.c make.c parse.c proc.c shell.c str.c suff.c targ.c  \
-       util.c var.c
-
-NOSHARED?=     YES
-
-CFLAGS+=-DMAKE_VERSION=\"5200408120\"
-
-# Make object files which depend on preprocessor symbols defined
-# in the Makefile which are not compilation options but rather
-# configuration options dependend on the Makefile. main.c needs
-# MAKE_VERSION, and DEFSHELLNAME.  This will cause recompilation
-# in the case the definition is changed in the makefile. It will
-# of course not cause recompilation if one does 'make MAKE_SHELL=csh'.
-main.o: ${MAKEFILE}
-
-# Directive and keyword tables. We use hash tables. These hash tables have been
-# generated with mph which can be found in pkgsrc/devel/mph.
-# If you change the directives or keywords (adding, deleting, reordering) you
-# need to create new tables and hash functions (directive_hash, keyword_hash).
-#
-# The following changes have been made to the generated code:
-#
-#      o prefix the names of the g, T0 and T1 arrays with 'directive_'
-#        resp. 'keyword_'.
-#
-#      o make the type of the tables 'const [un]signed char' (if you change
-#        anything make sure that the numbers fit into a char).
-#
-#      o make the hash function use the length for termination,
-#        not the trailing '\0', via the -l flag in emitc and some editing
-#        (only for directive_hash).
-
-LOCALBASE ?= /usr/pkg
-MPH    ?= ${LOCALBASE}/bin/mph
-EMITC  ?= ${LOCALBASE}/bin/emitc
-
-.PRECIOUS: hash
-
-hash:
-       ( echo '/*' ;                                                   \
-         echo ' * DO NOT EDIT' ;                                       \
-         echo -n ' * auto-generated from ' ;                           \
-         echo ${.CURDIR}/parse.c ;                                     \
-         echo ' */' ;                                                  \
-         echo '#include <sys/types.h>' ;                               \
-         echo ;                                                        \
-         echo '#include "hash_tables.h"' ;                             \
-         echo ;                                                        \
-         cat ${.CURDIR}/parse.c | sed                                  \
-           -e '1,/DIRECTIVES-START-TAG/d'                              \
-           -e '/DIRECTIVES-END-TAG/,$$d'                               \
-           -e 's/^[^"]*"\([^"]*\)".*$$/\1/' |                          \
-           ${MPH} -d2 -m1 | ${EMITC} -l -s |                           \
-           sed                                                         \
-           -e 's/^static int g\[\]/static const signed char directive_g[]/' \
-           -e 's/^static int T0\[\]/static const u_char directive_T0[]/' \
-           -e 's/^static int T1\[\]/static const u_char directive_T1[]/' \
-           -e '/^#define uchar unsigned char/d'                        \
-           -e 's/uchar/u_char/g'                                       \
-           -e 's/^hash(/directive_hash(/'                              \
-           -e 's/; \*kp;/; kp < key + len;/'                           \
-           -e 's/int len)/size_t len)/'                                \
-           -e 's/= T0\[/= directive_T0\[/'                             \
-           -e 's/= T1\[/= directive_T1\[/'                             \
-           -e 's/g\[f/directive_g[f/g' ;                               \
-         cat ${.CURDIR}/parse.c | sed                                  \
-           -e '1,/KEYWORD-START-TAG/d'                                 \
-           -e '/KEYWORD-END-TAG/,$$d'                                  \
-           -e 's/^[^"]*"\([^"]*\)".*$$/\1/' |                          \
-           ${MPH} -d2 -m1 | ${EMITC} -l -s |                           \
-           sed                                                         \
-           -e 's/^static int g\[\]/static const signed char keyword_g[]/' \
-           -e 's/^static int T0\[\]/static const u_char keyword_T0[]/' \
-           -e 's/^static int T1\[\]/static const u_char keyword_T1[]/' \
-           -e '/^#define uchar unsigned char/d'                        \
-           -e 's/uchar/u_char/g'                                       \
-           -e 's/^hash(/keyword_hash(/'                                \
-           -e 's/int len)/size_t len)/'                                \
-           -e 's/= T0\[/= keyword_T0\[/'                               \
-           -e 's/= T1\[/= keyword_T1\[/'                               \
-           -e 's/g\[f/keyword_g[f/g'                                   \
-       ) > ${.CURDIR}/hash_tables.c
-
-# Set the shell which make(1) uses.  Bourne is the default, but a decent
-# Korn shell works fine, and much faster.  Using the C shell for this
-# will almost certainly break everything, but it's Unix tradition to
-# allow you to shoot yourself in the foot if you want to :-)
-
-MAKE_SHELL?=   sh
-.if ${MAKE_SHELL} == "csh" || ${MAKE_SHELL} == "sh" || ${MAKE_SHELL} == "ksh"
-CFLAGS+=       -DDEFSHELLNAME=\"${MAKE_SHELL}\"
-.else
-.error "MAKE_SHELL must be set to one of \"csh\", \"sh\" or \"ksh\"."
-.endif
-
-.include <bsd.prog.mk>
diff --git a/usr.bin/make/Makefile.dist b/usr.bin/make/Makefile.dist
deleted file mode 100644 (file)
index 0e7a170..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-# $DragonFly: src/usr.bin/make/Makefile.dist,v 1.4 2005/06/16 20:44:13 okumoto Exp $
-# a very simple makefile...
-pmake:
-       @echo 'make started.'
-       cc -DDEFSHELLNAME=\"sh\" -I. -c *.c
-       cc *.o -o pmake
-       @echo 'make completed.'
diff --git a/usr.bin/make/PSD.doc/stubs b/usr.bin/make/PSD.doc/stubs
deleted file mode 100644 (file)
index 614d180..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-.\" $FreeBSD: src/usr.bin/make/PSD.doc/stubs,v 1.1.2.1 2000/11/24 10:08:45 ru Exp $
-.\" $DragonFly: src/usr.bin/make/PSD.doc/stubs,v 1.2 2003/06/17 04:29:29 dillon Exp $
-.\"
-.de Ix
-..
-.de Rd
-..
-.de Rm
-..
-.if n .ftr CR R
diff --git a/usr.bin/make/PSD.doc/tutorial.ms b/usr.bin/make/PSD.doc/tutorial.ms
deleted file mode 100644 (file)
index bf508fa..0000000
+++ /dev/null
@@ -1,3748 +0,0 @@
-.\" Copyright (c) 1988, 1989 by Adam de Boor
-.\" Copyright (c) 1989 by Berkeley Softworks
-.\" Copyright (c) 1988, 1989, 1993
-.\"    The Regents of the University of California.  All rights reserved.
-.\"
-.\" This code is derived from software contributed to Berkeley by
-.\" Adam de Boor.
-.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\"    notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\"    notice, this list of conditions and the following disclaimer in the
-.\"    documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\"    must display the following acknowledgement:
-.\"    This product includes software developed by the University of
-.\"    California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\"    may be used to endorse or promote products derived from this software
-.\"    without specific prior written permission.
-.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
-.\"
-.\"    @(#)tutorial.ms 8.1 (Berkeley) 8/18/93
-.\" $FreeBSD: src/usr.bin/make/PSD.doc/tutorial.ms,v 1.8.2.2 2000/11/24 10:08:45 ru Exp $
-.\" $DragonFly: src/usr.bin/make/PSD.doc/tutorial.ms,v 1.5 2004/11/24 07:20:51 dillon Exp $
-.\"
-.EH 'PSD:12-%''PMake \*- A Tutorial'
-.OH 'PMake \*- A Tutorial''PSD:12-%'
-.\" xH is a macro to provide numbered headers that are automatically stuffed
-.\" into a table-of-contents, properly indented, etc. If the first argument
-.\" is numeric, it is taken as the depth for numbering (as for .NH), else
-.\" the default (1) is assumed.
-.\"
-.\" @P The initial paragraph distance.
-.\" @Q The piece of section number to increment (or 0 if none given)
-.\" @R Section header.
-.\" @S Indent for toc entry
-.\" @T Argument to NH (can't use @Q b/c giving 0 to NH resets the counter)
-.de xH
-.NH \\$1
-\\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
-.nr PD .1v
-.XS \\n%
-.ta 0.6i
-\\*(SN \\$2 \\$3 \\$4 \\$5 \\$6 \\$7 \\$8 \\$9
-.XE
-.nr PD .3v
-..
-.ig
-.\" CW is used to place a string in fixed-width or switch to a
-.\" fixed-width font.
-.\" C is a typewriter font for a laserwriter. Use something else if
-.\" you don't have one...
-.de CW
-.ie !\\n(.$ .ft S
-.el \&\\$3\fS\\$1\fP\\$2
-..
-.\" Anything I put in a display I want to be in fixed-width
-.am DS
-.CW
-..
-.\" The stuff in .No produces a little stop sign in the left margin
-.\" that says NOTE in it. Unfortunately, it does cause a break, but
-.\" hey. Can't have everything. In case you're wondering how I came
-.\" up with such weird commands, they came from running grn on a
-.\" gremlin file...
-.de No
-.br
-.ne 0.5i
-.po -0.5i
-.br
-.mk 
-.nr g3 \\n(.f
-.nr g4 \\n(.s
-.ig ft
-.sp -1
-.\" .st cf
-\D's -1u'\D't 5u'
-.sp -1
-\h'50u'\D'l 71u 0u'\D'l 50u 50u'\D'l 0u 71u'\D'l -50u 50u'\D'l -71u 0u'\D'l -50u -50u'\D'l 0u -71u'\D'l 50u -50u'
-.sp -1
-\D't 3u'
-.sp -1
-.sp 7u
-\h'53u'\D'p 14 68u 0u 46u 46u 0u 68u -46u 46u -68u 0u -47u -46u 0u -68u 47u -46u'
-.sp -1
-.ft R
-.ps 6
-.nr g8 \\n(.d
-.ds g9 "NOTE
-.sp 74u
-\h'85u'\v'0.85n'\h\a-\w\a\\*(g9\au/2u\a\&\\*(g9
-.sp |\\n(g8u
-.sp 166u
-.ig br
-\D't 3u'\D's -1u'
-.br
-.po
-.rt 
-.ft \\n(g3
-.ps \\n(g4
-..
-.de Bp
-.ie !\\n(.$ .IP \(bu 2
-.el .IP "\&" 2
-..
-.po +.3i
-.TL
-PMake \*- A Tutorial
-.AU
-Adam de Boor
-.AI
-Berkeley Softworks
-2150 Shattuck Ave, Penthouse
-Berkeley, CA 94704
-adam@bsw.uu.net
-\&...!uunet!bsw!adam
-.FS
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appears in all copies.
-The University of California, Berkeley Softworks, and Adam de Boor make no
-representations about the suitability of this software for any
-purpose.  It is provided "as is" without express or implied warranty.
-.FE
-.PP
-.xH 1 Introduction
-.LP
-PMake is a program for creating other programs, or anything else you
-can think of for it to do.  The basic idea behind PMake is that, for
-any given system, be it a program or a document or whatever, there
-will be some files that depend on the state of other files (on when
-they were last modified). PMake takes these dependencies, which you
-must specify, and uses them to build whatever it is you want it to
-build.
-.LP
-PMake is almost fully-compatible with Make, with which you may already
-be familiar. PMake's most important feature is its ability to run
-several different jobs at once, making the creation of systems
-considerably faster. It also has a great deal more functionality than
-Make. Throughout the text, whenever something is mentioned that is an
-important difference between PMake and Make (i.e.  something that will
-cause a makefile to fail if you don't do something about it), or is
-simply important, it will be flagged with a little sign in the left
-margin, like this:
-.No
-.LP
-This tutorial is divided into three main sections corresponding to basic,
-intermediate and advanced PMake usage. If you already know Make well,
-you will only need to skim chapter 2 (there are some aspects of
-PMake that I consider basic to its use that didn't exist in Make).
-Things in chapter 3 make life much easier, while those in chapter 4
-are strictly for those who know what they are doing. Chapter 5 has
-definitions for the jargon I use and chapter 6 contains possible
-solutions to the problems presented throughout the tutorial.
-.xH 1 The Basics of PMake
-.LP
-PMake takes as input a file that tells a) which files depend on which
-other files to be complete and b) what to do about files that are
-``out-of-date.'' This file is known as a ``makefile'' and is usually
-.Ix 0 def makefile
-kept in the top-most directory of the system to be built. While you
-can call the makefile anything you want, PMake will look for
-.CW Makefile
-and
-.CW makefile
-(in that order) in the current directory if you don't tell it
-otherwise.
-.Ix 0 def makefile default
-To specify a different makefile, use the
-.B \-f
-flag (e.g.
-.CW "pmake -f program.mk" ''). ``
-.Ix 0 ref flags -f
-.Ix 0 ref makefile other
-.LP
-A makefile has four different types of lines in it:
-.RS
-.IP \(bu 2
-File dependency specifications
-.IP \(bu 2
-Creation commands
-.IP \(bu 2
-Variable assignments
-.IP \(bu 2
-Comments, include statements and conditional directives
-.RE
-.LP
-Any line may be continued over multiple lines by ending it with a
-backslash.
-.Ix 0 def "continuation line"
-The backslash, following newline and any initial whitespace
-on the following line are compressed into a single space before the
-input line is examined by PMake.
-.xH 2 Dependency Lines
-.LP
-As mentioned in the introduction, in any system, there are
-dependencies between the files that make up the system.  For instance,
-in a program made up of several C source files and one header file,
-the C files will need to be re-compiled should the header file be
-changed. For a document of several chapters and one macro file, the
-chapters will need to be reprocessed if any of the macros changes.
-.Ix 0 def "dependency"
-These are dependencies and are specified by means of dependency lines in
-the makefile.
-.LP
-.Ix 0 def "dependency line"
-On a dependency line, there are targets and sources, separated by a
-one- or two-character operator.
-The targets ``depend'' on the sources and are usually created from
-them.
-.Ix 0 def target
-.Ix 0 def source
-.Ix 0 ref operator
-Any number of targets and sources may be specified on a dependency line.
-All the targets in the line are made to depend on all the sources.
-Targets and sources need not be actual files, but every source must be
-either an actual file or another target in the makefile.
-If you run out of room, use a backslash at the end of the line to continue onto
-the next one.
-.LP
-Any file may be a target and any file may be a source, but the
-relationship between the two (or however many) is determined by the
-``operator'' that separates them.
-.Ix 0 def operator
-Three types of operators exist: one specifies that the datedness of a
-target is determined by the state of its sources, while another
-specifies other files (the sources) that need to be dealt with before
-the target can be re-created. The third operator is very similar to
-the first, with the additional condition that the target is
-out-of-date if it has no sources. These operations are represented by
-the colon, the exclamation point and the double-colon, respectively, and are
-mutually exclusive. Their exact semantics are as follows:
-.IP ":"
-.Ix 0 def operator colon
-.Ix 0 def :
-If a colon is used, a target on the line is considered to be
-``out-of-date'' (and in need of creation) if 
-.RS
-.IP \(bu 2
-any of the sources has been modified more recently than the target, or
-.IP \(bu 2
-the target doesn't exist.
-.RE
-.Ix 0 def out-of-date
-.IP "\&"
-Under this operation, steps will be taken to re-create the target only
-if it is found to be out-of-date by using these two rules.
-.IP "!"
-.Ix 0 def operator force
-.Ix 0 def !
-If an exclamation point is used, the target will always be re-created,
-but this will not happen until all of its sources have been examined
-and re-created, if necessary.
-.IP "::"
-.Ix 0 def operator double-colon
-.Ix 0 def ::
-If a double-colon is used, a target is out-of-date if:
-.RS
-.IP \(bu 2
-any of the sources has been modified more recently than the target, or
-.IP \(bu 2
-the target doesn't exist, or
-.IP \(bu 2
-the target has no sources.
-.RE
-.IP "\&"
-If the target is out-of-date according to these rules, it will be re-created.
-This operator also does something else to the targets, but I'll go
-into that in the next section (``Shell Commands'').
-.LP
-Enough words, now for an example. Take that C program I mentioned
-earlier. Say there are three C files
-.CW a.c , (
-.CW b.c
-and
-.CW  c.c )
-each of which
-includes the file
-.CW defs.h .
-The dependencies between the files could then be expressed as follows:
-.DS
-program         : a.o b.o c.o
-a.o b.o c.o     : defs.h
-a.o             : a.c
-b.o             : b.c
-c.o             : c.c
-.DE
-.LP
-You may be wondering at this point, where
-.CW a.o ,
-.CW b.o
-and
-.CW c.o
-came in and why
-.I they
-depend on
-.CW defs.h
-and the C files don't. The reason is quite simple:
-.CW program
-cannot be made by linking together .c files \*- it must be
-made from .o files. Likewise, if you change
-.CW defs.h ,
-it isn't the .c files that need to be re-created, it's the .o files.
-If you think of dependencies in these terms \*- which files (targets)
-need to be created from which files (sources) \*- you should have no problems.
-.LP
-An important thing to notice about the above example, is that all the
-\&.o files appear as targets on more than one line. This is perfectly
-all right: the target is made to depend on all the sources mentioned
-on all the dependency lines. E.g.
-.CW a.o
-depends on both
-.CW defs.h
-and
-.CW a.c .
-.Ix 0 ref dependency
-.No
-.LP
-The order of the dependency lines in the makefile is
-important: the first target on the first dependency line in the
-makefile will be the one that gets made if you don't say otherwise.
-That's why
-.CW program
-comes first in the example makefile, above.
-.LP
-Both targets and sources may contain the standard C-Shell wildcard
-characters
-.CW { , (
-.CW } ,
-.CW * ,
-.CW ? ,
-.CW [ ,
-and
-.CW ] ),
-but the non-curly-brace ones may only appear in the final component
-(the file portion) of the target or source. The characters mean the
-following things:
-.IP \fB{}\fP
-These enclose a comma-separated list of options and cause the pattern
-to be expanded once for each element of the list. Each expansion
-contains a different element. For example, 
-.CW src/{whiffle,beep,fish}.c
-expands to the three words
-.CW src/whiffle.c ,
-.CW src/beep.c ,
-and 
-.CW src/fish.c .
-These braces may be nested and, unlike the other wildcard characters,
-the resulting words need not be actual files. All other wildcard
-characters are expanded using the files that exist when PMake is
-started.
-.IP \fB*\fP
-This matches zero or more characters of any sort. 
-.CW src/*.c
-will expand to the same three words as above as long as 
-.CW src
-contains those three files (and no other files that end in 
-.CW .c ).
-.IP \fB?\fP
-Matches any single character.
-.IP \fB[]\fP
-This is known as a character class and contains either a list of
-single characters, or a series of character ranges 
-.CW a-z , (
-for example means all characters between a and z), or both. It matches
-any single character contained in the list. E.g.
-.CW [A-Za-z]
-will match all letters, while
-.CW [0123456789]
-will match all numbers.
-.xH 2 Shell Commands
-.LP
-``Isn't that nice,'' you say to yourself, ``but how are files
-actually `re-created,' as he likes to spell it?''
-The re-creation is accomplished by commands you place in the makefile.
-These commands are passed to the Bourne shell (better known as
-``/bin/sh'') to be executed and are
-.Ix 0 ref shell
-.Ix 0 ref re-creation
-.Ix 0 ref update
-expected to do what's necessary to update the target file (PMake
-doesn't actually check to see if the target was created. It just
-assumes it's there).
-.Ix 0 ref target
-.LP
-Shell commands in a makefile look a lot like shell commands you would
-type at a terminal, with one important exception: each command in a
-makefile
-.I must
-be preceded by at least one tab.
-.LP
-Each target has associated with it a shell script made up of
-one or more of these shell commands. The creation script for a target
-should immediately follow the dependency line for that target. While
-any given target may appear on more than one dependency line, only one
-of these dependency lines may be followed by a creation script, unless
-the `::' operator was used on the dependency line.
-.Ix 0 ref operator double-colon
-.Ix 0 ref ::
-.No
-.LP
-If the double-colon was used, each dependency line for the target
-may be followed by a shell script. That script will only be executed
-if the target on the associated dependency line is out-of-date with
-respect to the sources on that line, according to the rules I gave
-earlier.
-I'll give you a good example of this later on.
-.LP
-To expand on the earlier makefile, you might add commands as follows:
-.DS
-program         : a.o b.o c.o
-        cc a.o b.o c.o \-o program
-a.o b.o c.o     : defs.h
-a.o             : a.c
-        cc \-c a.c
-b.o             : b.c
-        cc \-c b.c
-c.o             : c.c
-        cc \-c c.c
-.DE
-.LP
-Something you should remember when writing a makefile is, the
-commands will be executed if the
-.I target
-on the dependency line is out-of-date, not the sources.
-.Ix 0 ref target
-.Ix 0 ref source
-.Ix 0 ref out-of-date
-In this example, the command
-.CW "cc \-c a.c" '' ``
-will be executed if
-.CW a.o
-is out-of-date. Because of the `:' operator,
-.Ix 0 ref :
-.Ix 0 ref operator colon
-this means that should
-.CW a.c
-.I or
-.CW defs.h
-have been modified more recently than
-.CW a.o ,
-the command will be executed
-.CW a.o "\&" (
-will be considered out-of-date).
-.Ix 0 ref out-of-date
-.LP
-Remember how I said the only difference between a makefile shell
-command and a regular shell command was the leading tab? I lied. There
-is another way in which makefile commands differ from regular ones.
-The first two characters after the initial whitespace are treated
-specially.
-If they are any combination of `@' and `\-', they cause PMake to do
-different things.
-.LP
-In most cases, shell commands are printed before they're
-actually executed. This is to keep you informed of what's going on. If
-an `@' appears, however, this echoing is suppressed. In the case of an
-.CW echo
-command, say
-.CW "echo Linking index" ,'' ``
-it would be
-rather silly to see
-.DS
-echo Linking index
-Linking index
-.DE
-.LP
-so PMake allows you to place an `@' before the command
-.CW "@echo Linking index" '') (``
-to prevent the command from being printed.
-.LP
-The other special character is the `\-'. In case you didn't know,
-shell commands finish with a certain ``exit status.'' This status is
-made available by the operating system to whatever program invoked the
-command. Normally this status will be 0 if everything went ok and
-non-zero if something went wrong. For this reason, PMake will consider
-an error to have occurred if one of the shells it invokes returns a non-zero
-status. When it detects an error, PMake's usual action is to abort
-whatever it's doing and exit with a non-zero status itself (any other
-targets that were being created will continue being made, but nothing
-new will be started. PMake will exit after the last job finishes).
-This behavior can be altered, however, by placing a `\-' at the front
-of a command
-.CW "\-mv index index.old" ''), (``
-certain command-line arguments,
-or doing other things, to be detailed later. In such
-a case, the non-zero status is simply ignored and PMake keeps chugging
-along.
-.No
-.LP
-Because all the commands are given to a single shell to execute, such
-things as setting shell variables, changing directories, etc., last
-beyond the command in which they are found. This also allows shell
-compound commands (like
-.CW for
-loops) to be entered in a natural manner.
-Since this could cause problems for some makefiles that depend on
-each command being executed by a single shell, PMake has a
-.B \-B
-.Ix 0 ref compatibility
-.Ix 0 ref flags -B
-flag (it stands for backwards-compatible) that forces each command to
-be given to a separate shell. It also does several other things, all
-of which I discourage since they are now old-fashioned.\|.\|.\|.
-.No
-.LP
-A target's shell script is fed to the shell on its (the shell's) input stream.
-This means that any commands, such as
-.CW ci
-that need to get input from the terminal won't work right \*- they'll
-get the shell's input, something they probably won't find to their
-liking. A simple way around this is to give a command like this:
-.DS
-ci $(SRCS) < /dev/tty
-.DE
-This would force the program's input to come from the terminal. If you
-can't do this for some reason, your only other alternative is to use
-PMake in its fullest compatibility mode. See 
-.B Compatibility
-in chapter 4.
-.Ix 0 ref compatibility
-.LP
-.xH 2 Variables
-.LP
-PMake, like Make before it, has the ability to save text in variables
-to be recalled later at your convenience. Variables in PMake are used
-much like variables in the shell and, by tradition, consist of
-all upper-case letters (you don't
-.I have
-to use all upper-case letters.
-In fact there's nothing to stop you from calling a variable
-.CW @^&$%$ .
-Just tradition). Variables are assigned-to using lines of the form
-.Ix 0 def variable assignment
-.DS
-VARIABLE = value
-.DE
-.Ix 0 def variable assignment
-appended-to by
-.DS
-VARIABLE += value
-.DE
-.Ix 0 def variable appending
-.Ix 0 def variable assignment appended
-.Ix 0 def +=
-conditionally assigned-to (if the variable isn't already defined) by
-.DS
-VARIABLE ?= value
-.DE
-.Ix 0 def variable assignment conditional
-.Ix 0 def ?=
-and assigned-to with expansion (i.e. the value is expanded (see below)
-before being assigned to the variable\*-useful for placing a value at
-the beginning of a variable, or other things) by
-.DS
-VARIABLE := value
-.DE
-.Ix 0 def variable assignment expanded
-.Ix 0 def :=
-.LP
-Any whitespace before
-.I value
-is stripped off. When appending, a space is placed between the old
-value and the stuff being appended.
-.LP
-The final way a variable may be assigned to is using
-.DS
-VARIABLE != shell-command
-.DE
-.Ix 0 def variable assignment shell-output
-.Ix 0 def !=
-In this case, 
-.I shell-command
-has all its variables expanded (see below) and is passed off to a
-shell to execute. The output of the shell is then placed in the
-variable. Any newlines (other than the final one) are replaced by
-spaces before the assignment is made. This is typically used to find
-the current directory via a line like:
-.DS
-CWD             != pwd
-.DE
-.LP
-.B Note:
-this is intended to be used to execute commands that produce small amounts
-of output (e.g. ``pwd''). The implementation is less than intelligent and will
-likely freeze if you execute something that produces thousands of
-bytes of output (8 Kb is the limit on many UNIX systems).
-.LP
-The value of a variable may be retrieved by enclosing the variable
-name in parentheses or curly braces and preceding the whole thing
-with a dollar sign.
-.LP
-For example, to set the variable CFLAGS to the string
-.CW "\-I/sprite/src/lib/libc \-O" ,'' ``
-you would place a line
-.DS
-CFLAGS = \-I/sprite/src/lib/libc \-O
-.DE
-in the makefile and use the word
-.CW "$(CFLAGS)"
-wherever you would like the string
-.CW "\-I/sprite/src/lib/libc \-O"
-to appear. This is called variable expansion.
-.Ix 0 def variable expansion
-.No
-.LP
-Unlike Make, PMake will not expand a variable unless it knows
-the variable exists. E.g. if you have a
-.CW "${i}"
-in a shell command and you have not assigned a value to the variable
-.CW i 
-(the empty string is considered a value, by the way), where Make would have
-substituted the empty string, PMake will leave the
-.CW "${i}"
-alone.
-To keep PMake from substituting for a variable it knows, precede the
-dollar sign with another dollar sign.
-(e.g. to pass
-.CW "${HOME}"
-to the shell, use
-.CW "$${HOME}" ).
-This causes PMake, in effect, to expand the
-.CW $
-macro, which expands to a single
-.CW $ .
-For compatibility, Make's style of variable expansion will be used
-if you invoke PMake with any of the compatibility flags (\c
-.B \-V ,
-.B \-B
-or
-.B \-M .
-The
-.B \-V
-flag alters just the variable expansion).
-.Ix 0 ref flags -V
-.Ix 0 ref flags -B
-.Ix 0 ref flags -M
-.Ix 0 ref compatibility
-.LP
-.Ix 0 ref variable expansion
-There are two different times at which variable expansion occurs:
-When parsing a dependency line, the expansion occurs immediately
-upon reading the line. If any variable used on a dependency line is
-undefined, PMake will print a message and exit.
-Variables in shell commands are expanded when the command is
-executed.
-Variables used inside another variable are expanded whenever the outer
-variable is expanded (the expansion of an inner variable has no effect
-on the outer variable. I.e. if the outer variable is used on a dependency
-line and in a shell command, and the inner variable changes value
-between when the dependency line is read and the shell command is
-executed, two different values will be substituted for the outer
-variable).
-.Ix 0 def variable types
-.LP
-Variables come in four flavors, though they are all expanded the same
-and all look about the same. They are (in order of expanding scope):
-.RS
-.IP \(bu 2
-Local variables.
-.Ix 0 ref variable local
-.IP \(bu 2
-Command-line variables.
-.Ix 0 ref variable command-line
-.IP \(bu 2
-Global variables.
-.Ix 0 ref variable global
-.IP \(bu 2
-Environment variables.
-.Ix 0 ref variable environment
-.RE
-.LP
-The classification of variables doesn't matter much, except that the
-classes are searched from the top (local) to the bottom (environment)
-when looking up a variable. The first one found wins.
-.xH 3 Local Variables
-.LP
-.Ix 0 def variable local
-Each target can have as many as seven local variables. These are
-variables that are only ``visible'' within that target's shell script
-and contain such things as the target's name, all of its sources (from
-all its dependency lines), those sources that were out-of-date, etc.
-Four local variables are defined for all targets. They are:
-.RS
-.IP ".TARGET"
-.Ix 0 def variable local .TARGET
-.Ix 0 def .TARGET
-The name of the target.
-.IP ".OODATE"
-.Ix 0 def variable local .OODATE
-.Ix 0 def .OODATE
-The list of the sources for the target that were considered out-of-date.
-The order in the list is not guaranteed to be the same as the order in
-which the dependencies were given.
-.IP ".ALLSRC"
-.Ix 0 def variable local .ALLSRC
-.Ix 0 def .ALLSRC
-The list of all sources for this target in the order in which they
-were given.
-.IP ".PREFIX"
-.Ix 0 def variable local .PREFIX
-.Ix 0 def .PREFIX
-The target without its suffix and without any leading path. E.g. for
-the target
-.CW ../../lib/compat/fsRead.c ,
-this variable would contain
-.CW fsRead .
-.RE
-.LP
-Three other local variables are set only for certain targets under
-special circumstances. These are the ``.IMPSRC,''
-.Ix 0 ref variable local .IMPSRC
-.Ix 0 ref .IMPSRC
-``.ARCHIVE,''
-.Ix 0 ref variable local .ARCHIVE
-.Ix 0 ref .ARCHIVE
-and ``.MEMBER''
-.Ix 0 ref variable local .MEMBER
-.Ix 0 ref .MEMBER
-variables. When they are set and how they are used is described later.
-.LP
-Four of these variables may be used in sources as well as in shell
-scripts.
-.Ix 0 def "dynamic source"
-.Ix 0 def source dynamic
-These are ``.TARGET'', ``.PREFIX'', ``.ARCHIVE'' and ``.MEMBER''. The
-variables in the sources are expanded once for each target on the
-dependency line, providing what is known as a ``dynamic source,''
-.Rd 0
-allowing you to specify several dependency lines at once. For example,
-.DS
-$(OBJS)         : $(.PREFIX).c
-.DE
-will create a dependency between each object file and its
-corresponding C source file.
-.xH 3 Command-line Variables
-.LP
-.Ix 0 def variable command-line
-Command-line variables are set when PMake is first invoked by giving a
-variable assignment as one of the arguments. For example,
-.DS
-pmake "CFLAGS = -I/sprite/src/lib/libc -O"
-.DE
-would make 
-.CW CFLAGS
-be a command-line variable with the given value. Any assignments to
-.CW CFLAGS
-in the makefile will have no effect, because once it
-is set, there is (almost) nothing you can do to change a command-line
-variable (the search order, you see). Command-line variables may be
-set using any of the four assignment operators, though only
-.CW =
-and
-.CW ?=
-behave as you would expect them to, mostly because assignments to
-command-line variables are performed before the makefile is read, thus
-the values set in the makefile are unavailable at the time.
-.CW +=
-.Ix 0 ref +=
-.Ix 0 ref variable assignment appended
-is the same as
-.CW = ,
-because the old value of the variable is sought only in the scope in
-which the assignment is taking place (for reasons of efficiency that I
-won't get into here).
-.CW :=
-and
-.CW ?=
-.Ix 0 ref :=
-.Ix 0 ref ?=
-.Ix 0 ref variable assignment expanded
-.Ix 0 ref variable assignment conditional
-will work if the only variables used are in the environment.
-.CW !=
-is sort of pointless to use from the command line, since the same
-effect can no doubt be accomplished using the shell's own command
-substitution mechanisms (backquotes and all that).
-.xH 3 Global Variables
-.LP
-.Ix 0 def variable global
-Global variables are those set or appended-to in the makefile.
-There are two classes of global variables: those you set and those PMake sets.
-As I said before, the ones you set can have any name you want them to have,
-except they may not contain a colon or an exclamation point.
-The variables PMake sets (almost) always begin with a
-period and always contain upper-case letters, only. The variables are
-as follows:
-.RS
-.IP .PMAKE
-.Ix 0 def variable global .PMAKE
-.Ix 0 def .PMAKE
-.Ix 0 def variable global MAKE
-.Ix 0 def MAKE
-The name by which PMake was invoked is stored in this variable. For
-compatibility, the name is also stored in the MAKE variable.
-.IP .MAKEFLAGS
-.Ix 0 def variable global .MAKEFLAGS
-.Ix 0 def .MAKEFLAGS variable
-.Ix 0 def variable global MFLAGS
-.Ix 0 def MFLAGS
-All the relevant flags with which PMake was invoked. This does not
-include such things as
-.B \-f
-or variable assignments. Again for compatibility, this value is stored
-in the MFLAGS variable as well.
-.RE
-.LP
-Two other variables, ``.INCLUDES'' and ``.LIBS,'' are covered in the
-section on special targets in chapter 3.
-.Ix 0 ref variable global .INCLUDES
-.Ix 0 ref variable global .LIBS
-.LP
-Global variables may be deleted using lines of the form:
-.Ix 0 def #undef
-.Ix 0 def variable deletion
-.DS
-#undef \fIvariable\fP
-.DE
-The
-.CW # ' `
-must be the first character on the line. Note that this may only be
-done on global variables.
-.xH 3 Environment Variables
-.LP
-.Ix 0 def variable environment
-Environment variables are passed by the shell that invoked PMake and
-are given by PMake to each shell it invokes. They are expanded like
-any other variable, but they cannot be altered in any way.
-.LP
-One special environment variable,
-.CW PMAKE ,
-.Ix 0 def variable environment PMAKE
-is examined by PMake for command-line flags, variable assignments,
-etc., it should always use. This variable is examined before the
-actual arguments to PMake are. In addition, all flags given to PMake,
-either through the
-.CW PMAKE
-variable or on the command line, are placed in this environment
-variable and exported to each shell PMake executes. Thus recursive
-invocations of PMake automatically receive the same flags as the
-top-most one.
-.LP
-Using all these variables, you can compress the sample makefile even more:
-.DS
-OBJS            = a.o b.o c.o
-program         : $(OBJS)
-        cc $(.ALLSRC) \-o $(.TARGET)
-$(OBJS)         : defs.h
-a.o             : a.c
-        cc \-c a.c
-b.o             : b.c
-        cc \-c b.c
-c.o             : c.c
-        cc \-c c.c
-.DE
-.Ix 0 ref variable local .ALLSRC
-.Ix 0 ref .ALLSRC
-.Ix 0 ref variable local .TARGET
-.Ix 0 ref .TARGET
-.Rd 3
-.xH 2 Comments
-.LP
-.Ix 0 def comments
-Comments in a makefile start with a `#' character and extend to the
-end of the line. They may appear
-anywhere you want them, except in a shell command (though the shell
-will treat it as a comment, too). If, for some reason, you need to use the `#'
-in a variable or on a dependency line, put a backslash in front of it.
-PMake will compress the two into a single `#' (Note: this isn't true
-if PMake is operating in full-compatibility mode).
-.Ix 0 ref flags -M
-.Ix 0 ref compatibility
-.xH 2 Parallelism
-.No
-.LP
-PMake was specifically designed to re-create several targets at once,
-when possible. You do not have to do anything special to cause this to
-happen (unless PMake was configured to not act in parallel, in which
-case you will have to make use of the
-.B \-L
-and
-.B \-J
-flags (see below)),
-.Ix 0 ref flags -L
-.Ix 0 ref flags -J
-but you do have to be careful at times.
-.LP
-There are several problems you are likely to encounter. One is
-that some makefiles (and programs) are written in such a way that it is
-impossible for two targets to be made at once. The program
-.CW xstr ,
-for example,
-always modifies the files
-.CW strings
-and
-.CW x.c .
-There is no way to change it. Thus you cannot run two of them at once
-without something being trashed. Similarly, if you have commands
-in the makefile that always send output to the same file, you will not
-be able to make more than one target at once unless you change the
-file you use. You can, for instance, add a
-.CW $$$$
-to the end of the file name to tack on the process ID of the shell
-executing the command (each
-.CW $$
-expands to a single
-.CW $ ,
-thus giving you the shell variable
-.CW $$ ).
-Since only one shell is used for all the
-commands, you'll get the same file name for each command in the
-script.
-.LP
-The other problem comes from improperly-specified dependencies that
-worked in Make because of its sequential, depth-first way of examining
-them. While I don't want to go into depth on how PMake
-works (look in chapter 4 if you're interested), I will warn you that
-files in two different ``levels'' of the dependency tree may be
-examined in a different order in PMake than they were in Make. For
-example, given the makefile
-.DS
-a               : b c
-b               : d
-.DE
-PMake will examine the targets in the order
-.CW c ,
-.CW d ,
-.CW b ,
-.CW a .
-If the makefile's author expected PMake to abort before making
-.CW c
-if an error occurred while making
-.CW b ,
-or if
-.CW b
-needed to exist before
-.CW c
-was made,
-s/he will be sorely disappointed. The dependencies are
-incomplete, since in both these cases,
-.CW c
-would depend on
-.CW b .
-So watch out.
-.LP
-Another problem you may face is that, while PMake is set up to handle the
-output from multiple jobs in a graceful fashion, the same is not so for input.
-It has no way to regulate input to different jobs,
-so if you use the redirection from
-.CW /dev/tty
-I mentioned earlier, you must be careful not to run two of the jobs at once.
-.xH 2 Writing and Debugging a Makefile
-.LP
-Now you know most of what's in a makefile, what do you do next? There
-are two choices: (1) use one of the uncommonly-available makefile
-generators or (2) write your own makefile (I leave out the third choice of
-ignoring PMake and doing everything by hand as being beyond the bounds
-of common sense).
-.LP
-When faced with the writing of a makefile, it is usually best to start
-from first principles: just what
-.I are
-you trying to do? What do you want the makefile finally to produce?
-.LP
-To begin with a somewhat traditional example, let's say you need to
-write a makefile to create a program,
-.CW expr ,
-that takes standard infix expressions and converts them to prefix form (for
-no readily apparent reason). You've got three source files, in C, that
-make up the program:
-.CW main.c ,
-.CW parse.c ,
-and
-.CW output.c .
-Harking back to my pithy advice about dependency lines, you write the
-first line of the file:
-.DS
-expr            : main.o parse.o output.o
-.DE
-because you remember
-.CW expr
-is made from
-.CW .o
-files, not
-.CW .c
-files. Similarly for the
-.CW .o
-files you produce the lines:
-.DS
-main.o          : main.c
-parse.o         : parse.c
-output.o        : output.c
-main.o parse.o output.o : defs.h
-.DE
-.LP
-Great. You've now got the dependencies specified. What you need now is
-commands. These commands, remember, must produce the target on the
-dependency line, usually by using the sources you've listed.
-You remember about local variables? Good, so it should come
-to you as no surprise when you write
-.DS
-expr            : main.o parse.o output.o
-        cc -o $(.TARGET) $(.ALLSRC)
-.DE
-Why use the variables? If your program grows to produce postfix
-expressions too (which, of course, requires a name change or two), it
-is one fewer place you have to change the file. You cannot do this for
-the object files, however, because they depend on their corresponding
-source files
-.I and
-.CW defs.h ,
-thus if you said
-.DS
-       cc -c $(.ALLSRC)
-.DE
-you'd get (for
-.CW main.o ):
-.DS
-       cc -c main.c defs.h
-.DE
-which is wrong. So you round out the makefile with these lines:
-.DS
-main.o          : main.c
-        cc -c main.c
-parse.o         : parse.c
-        cc -c parse.c
-output.o        : output.c
-        cc -c output.c
-.DE
-.LP
-The makefile is now complete and will, in fact, create the program you
-want it to without unnecessary compilations or excessive typing on
-your part. There are two things wrong with it, however (aside from it
-being altogether too long, something I'll address in chapter 3):
-.IP 1)
-The string
-.CW "main.o parse.o output.o" '' ``
-is repeated twice, necessitating two changes when you add postfix
-(you were planning on that, weren't you?). This is in direct violation
-of de Boor's First Rule of writing makefiles:
-.QP
-.I
-Anything that needs to be written more than once
-should be placed in a variable.
-.IP "\&"
-I cannot emphasize this enough as being very important to the
-maintenance of a makefile and its program.
-.IP 2)
-There is no way to alter the way compilations are performed short of
-editing the makefile and making the change in all places. This is evil
-and violates de Boor's Second Rule, which follows directly from the
-first:
-.QP
-.I
-Any flags or programs used inside a makefile should be placed in a variable so
-they may be changed, temporarily or permanently, with the greatest ease.
-.LP
-The makefile should more properly read:
-.DS
-OBJS            = main.o parse.o output.o
-expr            : $(OBJS)
-        $(CC) $(CFLAGS) -o $(.TARGET) $(.ALLSRC)
-main.o          : main.c
-        $(CC) $(CFLAGS) -c main.c
-parse.o         : parse.c
-        $(CC) $(CFLAGS) -c parse.c
-output.o        : output.c
-        $(CC) $(CFLAGS) -c output.c
-$(OBJS)         : defs.h
-.DE
-Alternatively, if you like the idea of dynamic sources mentioned in
-section 2.3.1,
-.Rm 0 2.3.1
-.Rd 4
-.Ix 0 ref "dynamic source"
-.Ix 0 ref source dynamic
-you could write it like this:
-.DS
-OBJS            = main.o parse.o output.o
-expr            : $(OBJS)
-        $(CC) $(CFLAGS) -o $(.TARGET) $(.ALLSRC)
-$(OBJS)         : $(.PREFIX).c defs.h
-        $(CC) $(CFLAGS) -c $(.PREFIX).c
-.DE
-These two rules and examples lead to de Boor's First Corollary:
-.QP
-.I
-Variables are your friends.
-.LP
-Once you've written the makefile comes the sometimes-difficult task of
-.Ix 0 ref debugging
-making sure the darn thing works. Your most helpful tool to make sure
-the makefile is at least syntactically correct is the
-.B \-n
-.Ix 0 ref flags -n
-flag, which allows you to see if PMake will choke on the makefile. The
-second thing the
-.B \-n
-flag lets you do is see what PMake would do without it actually doing
-it, thus you can make sure the right commands would be executed were
-you to give PMake its head.
-.LP
-When you find your makefile isn't behaving as you hoped, the first
-question that comes to mind (after ``What time is it, anyway?'') is
-``Why not?'' In answering this, two flags will serve you well:
-.CW "-d m" '' ``
-.Ix 0 ref flags -d
-and
-.CW "-p 2" .'' ``
-.Ix 0 ref flags -p
-The first causes PMake to tell you as it examines each target in the
-makefile and indicate why it is deciding whatever it is deciding. You
-can then use the information printed for other targets to see where
-you went wrong. The
-.CW "-p 2" '' ``
-flag makes PMake print out its internal state when it is done,
-allowing you to see that you forgot to make that one chapter depend on
-that file of macros you just got a new version of. The output from
-.CW "-p 2" '' ``
-is intended to resemble closely a real makefile, but with additional
-information provided and with variables expanded in those commands
-PMake actually printed or executed.
-.LP
-Something to be especially careful about is circular dependencies.
-.Ix 0 def dependency circular
-E.g.
-.DS
-a              : b
-b              : c d
-d              : a
-.DE
-In this case, because of how PMake works,
-.CW c
-is the only thing PMake will examine, because
-.CW d
-and
-.CW a
-will effectively fall off the edge of the universe, making it
-impossible to examine
-.CW b
-(or them, for that matter).
-PMake will tell you (if run in its normal mode) all the targets
-involved in any cycle it looked at (i.e. if you have two cycles in the
-graph (naughty, naughty), but only try to make a target in one of
-them, PMake will only tell you about that one. You'll have to try to
-make the other to find the second cycle). When run as Make, it will
-only print the first target in the cycle.
-.xH 2 Invoking PMake
-.LP
-.Ix 0 ref flags
-.Ix 0 ref arguments
-.Ix 0 ref usage
-PMake comes with a wide variety of flags to choose from.
-They may appear in any order, interspersed with command-line variable
-assignments and targets to create.
-The flags are as follows:
-.IP "\fB\-d\fP \fIwhat\fP"
-.Ix 0 def flags -d
-.Ix 0 ref debugging
-This causes PMake to spew out debugging information that
-may prove useful to you. If you can't
-figure out why PMake is doing what it's doing, you might try using
-this flag. The
-.I what
-parameter is a string of single characters that tell PMake what
-aspects you are interested in. Most of what I describe will make
-little sense to you, unless you've dealt with Make before. Just
-remember where this table is and come back to it as you read on.
-The characters and the information they produce are as follows:
-.RS
-.IP a
-Archive searching and caching.
-.IP c
-Conditional evaluation.
-.IP d
-The searching and caching of directories.
-.IP j
-Various snippets of information related to the running of the multiple
-shells. Not particularly interesting.
-.IP m
-The making of each target: what target is being examined; when it was
-last modified; whether it is out-of-date; etc.
-.IP p
-Makefile parsing.
-.IP r
-Remote execution.
-.IP s
-The application of suffix-transformation rules. (See chapter 3)
-.IP t
-The maintenance of the list of targets.
-.IP v
-Variable assignment.
-.RE
-.IP "\&"
-Of these all, the
-.CW m
-and
-.CW s
-letters will be most useful to you.
-If the
-.B \-d
-is the final argument or the argument from which it would get these
-key letters (see below for a note about which argument would be used)
-begins with a
-.B \- ,
-all of these debugging flags will be set, resulting in massive amounts
-of output.
-.IP "\fB\-f\fP \fImakefile\fP"
-.Ix 0 def flags -f
-Specify a makefile to read different from the standard makefiles
-.CW Makefile "\&" (
-or
-.CW makefile ).
-.Ix 0 ref makefile default
-.Ix 0 ref makefile other
-If
-.I makefile
-is ``\-'', PMake uses the standard input. This is useful for making
-quick and dirty makefiles.\|.\|.
-.Ix 0 ref makefile "quick and dirty"
-.IP \fB\-h\fP
-.Ix 0 def flags -h
-Prints out a summary of the various flags PMake accepts. It can also
-be used to find out what level of concurrency was compiled into the
-version of PMake you are using (look at
-.B \-J
-and
-.B \-L )
-and various other information on how PMake was configured.
-.Ix 0 ref configuration
-.Ix 0 ref makefilesystem
-.IP \fB\-i\fP
-.Ix 0 def flags -i
-If you give this flag, PMake will ignore non-zero status returned
-by any of its shells. It's like placing a `\-' before all the commands
-in the makefile.
-.IP \fB\-k\fP
-.Ix 0 def flags -k
-This is similar to
-.B \-i
-in that it allows PMake to continue when it sees an error, but unlike
-.B \-i ,
-where PMake continues blithely as if nothing went wrong,
-.B \-k
-causes it to recognize the error and only continue work on those
-things that don't depend on the target, either directly or indirectly (through
-depending on something that depends on it), whose creation returned the error.
-The `k' is for ``keep going''.\|.\|.
-.Ix 0 ref target
-.IP \fB\-l\fP
-.Ix 0 def flags -l
-PMake has the ability to lock a directory against other
-people executing it in the same directory (by means of a file called
-``LOCK.make'' that it creates and checks for in the directory). This
-is a Good Thing because two people doing the same thing in the same place
-can be disastrous for the final product (too many cooks and all that).
-Whether this locking is the default is up to your system
-administrator. If locking is on,
-.B \-l
-will turn it off, and vice versa. Note that this locking will not
-prevent \fIyou\fP from invoking PMake twice in the same place \*- if
-you own the lock file, PMake will warn you about it but continue to execute.
-.IP "\fB\-m\fP \fIdirectory\fP"
-.Ix 0 def flags -m
-Tells PMake another place to search for included makefiles via the <...>
-style.  Several
-.B \-m
-options can be given to form a search path.  If this construct is used the
-default system makefile search path is completely overridden.
-To be explained in chapter 3, section 3.2.
-.Rm 2 3.2
-.IP \fB\-n\fP
-.Ix 0 def flags -n
-This flag tells PMake not to execute the commands needed to update the
-out-of-date targets in the makefile. Rather, PMake will simply print
-the commands it would have executed and exit. This is particularly
-useful for checking the correctness of a makefile. If PMake doesn't do
-what you expect it to, it's a good chance the makefile is wrong.
-.IP "\fB\-p\fP \fInumber\fP"
-.Ix 0 def flags -p
-.Ix 0 ref debugging
-This causes PMake to print its input in a reasonable form, though
-not necessarily one that would make immediate sense to anyone but me. The
-.I number
-is a bitwise-or of 1 and 2 where 1 means it should print the input
-before doing any processing and 2 says it should print it after
-everything has been re-created. Thus
-.CW "\-p 3"
-would print it twice\*-once before processing and once after (you
-might find the difference between the two interesting). This is mostly
-useful to me, but you may find it informative in some bizarre circumstances.
-.IP \fB\-q\fP
-.Ix 0 def flags -q
-If you give PMake this flag, it will not try to re-create anything. It
-will just see if anything is out-of-date and exit non-zero if so.
-.IP \fB\-r\fP
-.Ix 0 def flags -r
-When PMake starts up, it reads a default makefile that tells it what
-sort of system it's on and gives it some idea of what to do if you
-don't tell it anything. I'll tell you about it in chapter 3. If you
-give this flag, PMake won't read the default makefile.
-.IP \fB\-s\fP
-.Ix 0 def flags -s
-This causes PMake to not print commands before they're executed. It
-is the equivalent of putting an `@' before every command in the
-makefile.
-.IP \fB\-t\fP
-.Ix 0 def flags -t
-Rather than try to re-create a target, PMake will simply ``touch'' it
-so as to make it appear up-to-date. If the target didn't exist before,
-it will when PMake finishes, but if the target did exist, it will
-appear to have been updated.
-.IP \fB\-v\fP
-.Ix 0 def flags -v
-This is a mixed-compatibility flag intended to mimic the System V
-version of Make. It is the same as giving
-.B \-B ,
-and
-.B \-V
-as well as turning off directory locking. Targets can still be created
-in parallel, however. This is the mode PMake will enter if it is
-invoked either as
-.CW smake '' ``
-or
-.CW vmake ''. ``
-.IP \fB\-x\fP
-.Ix 0 def flags -x
-This tells PMake it's ok to export jobs to other machines, if they're
-available. It is used when running in Make mode, as exporting in this
-mode tends to make things run slower than if the commands were just
-executed locally.
-.IP \fB\-B\fP
-.Ix 0 ref compatibility
-.Ix 0 def flags -B
-Forces PMake to be as backwards-compatible with Make as possible while
-still being itself.
-This includes:
-.RS
-.IP \(bu 2
-Executing one shell per shell command
-.IP \(bu 2
-Expanding anything that looks even vaguely like a variable, with the
-empty string replacing any variable PMake doesn't know.
-.IP \(bu 2
-Refusing to allow you to escape a `#' with a backslash.
-.IP \(bu 2
-Permitting undefined variables on dependency lines and conditionals
-(see below). Normally this causes PMake to abort.
-.RE
-.IP \fB\-C\fP
-.Ix 0 def flags -C
-This nullifies any and all compatibility mode flags you may have given
-or implied up to the time the
-.B \-C
-is encountered. It is useful mostly in a makefile that you wrote for PMake
-to avoid bad things happening when someone runs PMake as
-.CW make '' ``
-or has things set in the environment that tell it to be compatible.
-.B \-C
-is
-.I not
-placed in the
-.CW PMAKE
-environment variable or the
-.CW .MAKEFLAGS
-or
-.CW MFLAGS
-global variables.
-.Ix 0 ref variable environment PMAKE
-.Ix 0 ref variable global .MAKEFLAGS
-.Ix 0 ref variable global MFLAGS
-.Ix 0 ref .MAKEFLAGS variable
-.Ix 0 ref MFLAGS
-.IP "\fB\-D\fP \fIvariable\fP"
-.Ix 0 def flags -D
-Allows you to define a variable to have 
-.CW 1 '' ``
-as its value.  The variable is a global variable, not a command-line
-variable. This is useful mostly for people who are used to the C
-compiler arguments and those using conditionals, which I'll get into
-in section 4.3
-.Rm 1 4.3
-.IP "\fB\-I\fP \fIdirectory\fP"
-.Ix 0 def flags -I
-Tells PMake another place to search for included makefiles. Yet
-another thing to be explained in chapter 3 (section 3.2, to be
-precise).
-.Rm 2 3.2
-.IP "\fB\-J\fP \fInumber\fP"
-.Ix 0 def flags -J
-Gives the absolute maximum number of targets to create at once on both
-local and remote machines.
-.IP "\fB\-L\fP \fInumber\fP"
-.Ix 0 def flags -L
-This specifies the maximum number of targets to create on the local
-machine at once. This may be 0, though you should be wary of doing
-this, as PMake may hang until a remote machine becomes available, if
-one is not available when it is started.
-.IP \fB\-M\fP
-.Ix 0 ref compatibility
-.Ix 0 def flags -M
-This is the flag that provides absolute, complete, full compatibility
-with Make. It still allows you to use all but a few of the features of
-PMake, but it is non-parallel. This is the mode PMake enters if you
-call it
-.CW make .'' ``
-.IP \fB\-P\fP
-.Ix 0 def flags -P
-.Ix 0 ref "output control"
-When creating targets in parallel, several shells are executing at
-once, each wanting to write its own two cent's-worth to the screen.
-This output must be captured by PMake in some way in order to prevent
-the screen from being filled with garbage even more indecipherable
-than you usually see. PMake has two ways of doing this, one of which
-provides for much cleaner output and a clear separation between the
-output of different jobs, the other of which provides a more immediate
-response so one can tell what is really happening. The former is done
-by notifying you when the creation of a target starts, capturing the
-output and transferring it to the screen all at once when the job
-finishes. The latter is done by catching the output of the shell (and
-its children) and buffering it until an entire line is received, then
-printing that line preceded by an indication of which job produced
-the output. Since I prefer this second method, it is the one used by
-default. The first method will be used if you give the
-.B \-P
-flag to PMake.
-.IP \fB\-V\fP
-.Ix 0 def flags -V
-As mentioned before, the
-.B \-V
-flag tells PMake to use Make's style of expanding variables,
-substituting the empty string for any variable it doesn't know.
-.IP \fB\-W\fP
-.Ix 0 def flags -W
-There are several times when PMake will print a message at you that is
-only a warning, i.e. it can continue to work in spite of your having
-done something silly (such as forgotten a leading tab for a shell
-command). Sometimes you are well aware of silly things you have done
-and would like PMake to stop bothering you. This flag tells it to shut
-up about anything non-fatal.
-.IP \fB\-X\fP
-.Ix 0 def flags -X
-This flag causes PMake to not attempt to export any jobs to another
-machine.
-.LP
-Several flags may follow a single `\-'. Those flags that require
-arguments take them from successive parameters. E.g.
-.DS
-pmake -fDnI server.mk DEBUG /chip2/X/server/include
-.DE
-will cause PMake to read
-.CW server.mk
-as the input makefile, define the variable
-.CW DEBUG
-as a global variable and look for included makefiles in the directory
-.CW /chip2/X/server/include .
-.xH 2 Summary
-.LP
-A makefile is made of four types of lines:
-.RS
-.IP \(bu 2
-Dependency lines
-.IP \(bu 2
-Creation commands
-.IP \(bu 2
-Variable assignments
-.IP \(bu 2
-Comments, include statements and conditional directives
-.RE
-.LP
-A dependency line is a list of one or more targets, an operator
-.CW : ', (`
-.CW :: ', `
-or
-.CW ! '), `
-and a list of zero or more sources. Sources may contain wildcards and
-certain local variables.
-.LP
-A creation command is a regular shell command preceded by a tab. In
-addition, if the first two characters after the tab (and other
-whitespace) are a combination of
-.CW @ ' `
-or
-.CW - ', `
-PMake will cause the command to not be printed (if the character is
-.CW @ ') `
-or errors from it to be ignored (if
-.CW - '). `
-A blank line, dependency line or variable assignment terminates a
-creation script. There may be only one creation script for each target
-with a
-.CW : ' `
-or
-.CW ! ' `
-operator.
-.LP
-Variables are places to store text. They may be unconditionally
-assigned-to using the
-.CW = ' `
-.Ix 0 ref =
-.Ix 0 ref variable assignment
-operator, appended-to using the
-.CW += ' `
-.Ix 0 ref +=
-.Ix 0 ref variable assignment appended
-operator, conditionally (if the variable is undefined) assigned-to
-with the
-.CW ?= ' `
-.Ix 0 ref ?=
-.Ix 0 ref variable assignment conditional
-operator, and assigned-to with variable expansion with the
-.CW := ' `
-.Ix 0 ref :=
-.Ix 0 ref variable assignment expanded
-operator. The output of a shell command may be assigned to a variable
-using the
-.CW != ' `
-.Ix 0 ref !=
-.Ix 0 ref variable assignment shell-output
-operator.  Variables may be expanded (their value inserted) by enclosing
-their name in parentheses or curly braces, preceded by a dollar sign.
-A dollar sign may be escaped with another dollar sign. Variables are
-not expanded if PMake doesn't know about them. There are seven local
-variables:
-.CW .TARGET ,
-.CW .ALLSRC ,
-.CW .OODATE ,
-.CW .PREFIX ,
-.CW .IMPSRC ,
-.CW .ARCHIVE ,
-and
-.CW .MEMBER .
-Four of them
-.CW .TARGET , (
-.CW .PREFIX ,
-.CW .ARCHIVE ,
-and
-.CW .MEMBER )
-may be used to specify ``dynamic sources.''
-.Ix 0 ref "dynamic source"
-.Ix 0 ref source dynamic
-Variables are good. Know them. Love them. Live them.
-.LP
-Debugging of makefiles is best accomplished using the
-.B \-n ,
-.B "\-d m" ,
-and
-.B "\-p 2"
-flags.
-.xH 2 Exercises
-.ce
-\s+4\fBTBA\fP\s0
-.xH 1 Short-cuts and Other Nice Things
-.LP
-Based on what I've told you so far, you may have gotten the impression
-that PMake is just a way of storing away commands and making sure you
-don't forget to compile something. Good. That's just what it is.
-However, the ways I've described have been inelegant, at best, and
-painful, at worst.
-This chapter contains things that make the
-writing of makefiles easier and the makefiles themselves shorter and
-easier to modify (and, occasionally, simpler). In this chapter, I
-assume you are somewhat more
-familiar with Sprite (or UNIX, if that's what you're using) than I did
-in chapter 2, just so you're on your toes.
-So without further ado...
-.xH 2 Transformation Rules
-.LP
-As you know, a file's name consists of two parts: a base name, which
-gives some hint as to the contents of the file, and a suffix, which
-usually indicates the format of the file.
-Over the years, as
-.UX
-has developed,
-naming conventions, with regard to suffixes, have also developed that have
-become almost as incontrovertible as Law. E.g. a file ending in
-.CW .c
-is assumed to contain C source code; one with a
-.CW .o
-suffix is assumed to be a compiled, relocatable object file that may
-be linked into any program; a file with a
-.CW .ms
-suffix is usually a text file to be processed by Troff with the \-ms
-macro package, and so on.
-One of the best aspects of both Make and PMake comes from their
-understanding of how the suffix of a file pertains to its contents and
-their ability to do things with a file based solely on its suffix. This
-ability comes from something known as a transformation rule. A
-transformation rule specifies how to change a file with one suffix
-into a file with another suffix.
-.LP
-A transformation rule looks much like a dependency line, except the
-target is made of two known suffixes stuck together. Suffixes are made
-known to PMake by placing them as sources on a dependency line whose
-target is the special target
-.CW .SUFFIXES .
-E.g.
-.DS
-\&.SUFFIXES       : .o .c
-\&.c.o            :
-        $(CC) $(CFLAGS) -c $(.IMPSRC)
-.DE
-The creation script attached to the target is used to transform a file with
-the first suffix (in this case,
-.CW .c )
-into a file with the second suffix (here,
-.CW .o ).
-In addition, the target inherits whatever attributes have been applied
-to the transformation rule.
-The simple rule given above says that to transform a C source file
-into an object file, you compile it using
-.CW cc
-with the
-.CW \-c
-flag.
-This rule is taken straight from the system makefile. Many
-transformation rules (and suffixes) are defined there, and I refer you
-to it for more examples (type
-.CW "pmake -h" '' ``
-to find out where it is).
-.LP
-There are several things to note about the transformation rule given
-above:
-.RS
-.IP 1)
-The
-.CW .IMPSRC 
-variable.
-.Ix 0 def variable local .IMPSRC
-.Ix 0 def .IMPSRC
-This variable is set to the ``implied source'' (the file from which
-the target is being created; the one with the first suffix), which, in this
-case, is the .c file.
-.IP 2)
-The
-.CW CFLAGS
-variable. Almost all of the transformation rules in the system
-makefile are set up using variables that you can alter in your
-makefile to tailor the rule to your needs. In this case, if you want
-all your C files to be compiled with the
-.B \-g
-flag, to provide information for
-.CW dbx ,
-you would set the
-.CW CFLAGS
-variable to contain
-.CW -g
-.CW "CFLAGS = -g" '') (``
-and PMake would take care of the rest.
-.RE
-.LP
-To give you a quick example, the makefile in 2.3.4 
-.Rm 3 2.3.4
-could be changed to this:
-.DS
-OBJS            = a.o b.o c.o
-program         : $(OBJS)
-        $(CC) -o $(.TARGET) $(.ALLSRC)
-$(OBJS)         : defs.h
-.DE
-The transformation rule I gave above takes the place of the 6 lines\**
-.FS
-This is also somewhat cleaner, I think, than the dynamic source
-solution presented in 2.6
-.FE
-.Rm 4 2.6
-.DS
-a.o             : a.c
-        cc -c a.c
-b.o             : b.c
-        cc -c b.c
-c.o             : c.c
-        cc -c c.c
-.DE
-.LP
-Now you may be wondering about the dependency between the
-.CW .o
-and
-.CW .c
-files \*- it's not mentioned anywhere in the new makefile. This is
-because it isn't needed: one of the effects of applying a
-transformation rule is the target comes to depend on the implied
-source. That's why it's called the implied
-.I source .
-.LP
-For a more detailed example. Say you have a makefile like this:
-.DS
-a.out           : a.o b.o
-        $(CC) $(.ALLSRC)
-.DE
-and a directory set up like this:
-.DS
-total 4
--rw-rw-r--  1 deboor         34 Sep  7 00:43 Makefile
--rw-rw-r--  1 deboor        119 Oct  3 19:39 a.c
--rw-rw-r--  1 deboor        201 Sep  7 00:43 a.o
--rw-rw-r--  1 deboor         69 Sep  7 00:43 b.c
-.DE
-While just typing
-.CW pmake '' ``
-will do the right thing, it's much more informative to type
-.CW "pmake -d s" ''. ``
-This will show you what PMake is up to as it processes the files. In
-this case, PMake prints the following:
-.DS
-Suff_FindDeps (a.out)
-       using existing source a.o
-       applying .o -> .out to "a.o"
-Suff_FindDeps (a.o)
-       trying a.c...got it
-       applying .c -> .o to "a.c"
-Suff_FindDeps (b.o)
-       trying b.c...got it
-       applying .c -> .o to "b.c"
-Suff_FindDeps (a.c)
-       trying a.y...not there
-       trying a.l...not there
-       trying a.c,v...not there
-       trying a.y,v...not there
-       trying a.l,v...not there
-Suff_FindDeps (b.c)
-       trying b.y...not there
-       trying b.l...not there
-       trying b.c,v...not there
-       trying b.y,v...not there
-       trying b.l,v...not there
---- a.o ---
-cc  -c a.c
---- b.o ---
-cc  -c b.c
---- a.out ---
-cc a.o b.o
-.DE
-.LP
-.CW Suff_FindDeps
-is the name of a function in PMake that is called to check for implied
-sources for a target using transformation rules.
-The transformations it tries are, naturally
-enough, limited to the ones that have been defined (a transformation
-may be defined multiple times, by the way, but only the most recent
-one will be used). You will notice, however, that there is a definite
-order to the suffixes that are tried. This order is set by the
-relative positions of the suffixes on the
-.CW .SUFFIXES
-line \*- the earlier a suffix appears, the earlier it is checked as
-the source of a transformation. Once a suffix has been defined, the
-only way to change its position in the pecking order is to remove all
-the suffixes (by having a
-.CW .SUFFIXES
-dependency line with no sources) and redefine them in the order you
-want. (Previously-defined transformation rules will be automatically
-redefined as the suffixes they involve are re-entered.)
-.LP
-Another way to affect the search order is to make the dependency
-explicit. In the above example,
-.CW a.out
-depends on
-.CW a.o
-and
-.CW b.o .
-Since a transformation exists from
-.CW .o
-to
-.CW .out ,
-PMake uses that, as indicated by the
-.CW "using existing source a.o" '' ``
-message.
-.LP
-The search for a transformation starts from the suffix of the target
-and continues through all the defined transformations, in the order
-dictated by the suffix ranking, until an existing file with the same
-base (the target name minus the suffix and any leading directories) is
-found. At that point, one or more transformation rules will have been
-found to change the one existing file into the target.
-.LP
-For example, ignoring what's in the system makefile for now, say you
-have a makefile like this:
-.DS
-\&.SUFFIXES       : .out .o .c .y .l
-\&.l.c            :
-        lex $(.IMPSRC)
-        mv lex.yy.c $(.TARGET)
-\&.y.c            :
-        yacc $(.IMPSRC)
-        mv y.tab.c $(.TARGET)
-\&.c.o            :
-        cc -c $(.IMPSRC)
-\&.o.out          :
-        cc -o $(.TARGET) $(.IMPSRC)
-.DE
-and the single file
-.CW jive.l .
-If you were to type
-.CW "pmake -rd ms jive.out" ,'' ``
-you would get the following output for
-.CW jive.out :
-.DS
-Suff_FindDeps (jive.out)
-       trying jive.o...not there
-       trying jive.c...not there
-       trying jive.y...not there
-       trying jive.l...got it
-       applying .l -> .c to "jive.l"
-       applying .c -> .o to "jive.c"
-       applying .o -> .out to "jive.o"
-.DE
-and this is why: PMake starts with the target
-.CW jive.out ,
-figures out its suffix
-.CW .out ) (
-and looks for things it can transform to a
-.CW .out
-file. In this case, it only finds
-.CW .o ,
-so it looks for the file
-.CW jive.o .
-It fails to find it, so it looks for transformations into a
-.CW .o
-file. Again it has only one choice:
-.CW .c .
-So it looks for
-.CW jive.c
-and, as you know, fails to find it. At this point it has two choices:
-it can create the
-.CW .c
-file from either a
-.CW .y
-file or a
-.CW .l
-file. Since
-.CW .y
-came first on the
-.CW .SUFFIXES
-line, it checks for
-.CW jive.y
-first, but can't find it, so it looks for
-.CW jive.l
-and, lo and behold, there it is.
-At this point, it has defined a transformation path as follows:
-.CW .l
-\(->
-.CW .c
-\(->
-.CW .o
-\(->
-.CW .out
-and applies the transformation rules accordingly. For completeness,
-and to give you a better idea of what PMake actually did with this
-three-step transformation, this is what PMake printed for the rest of
-the process:
-.DS
-Suff_FindDeps (jive.o)
-       using existing source jive.c
-       applying .c -> .o to "jive.c"
-Suff_FindDeps (jive.c)
-       using existing source jive.l
-       applying .l -> .c to "jive.l"
-Suff_FindDeps (jive.l)
-Examining jive.l...modified 17:16:01 Oct 4, 1987...up-to-date
-Examining jive.c...non-existent...out-of-date
---- jive.c ---
-lex jive.l
-\&.\|.\|. meaningless lex output deleted .\|.\|.
-mv lex.yy.c jive.c
-Examining jive.o...non-existent...out-of-date
---- jive.o ---
-cc -c jive.c
-Examining jive.out...non-existent...out-of-date
---- jive.out ---
-cc -o jive.out jive.o
-.DE
-.LP
-One final question remains: what does PMake do with targets that have
-no known suffix? PMake simply pretends it actually has a known suffix
-and searches for transformations accordingly.
-The suffix it chooses is the source for the
-.CW .NULL
-.Ix 0 ref .NULL
-target mentioned later. In the system makefile, 
-.CW .out
-is chosen as the ``null suffix''
-.Ix 0 def suffix null
-.Ix 0 def "null suffix"
-because most people use PMake to create programs. You are, however,
-free and welcome to change it to a suffix of your own choosing.
-The null suffix is ignored, however, when PMake is in compatibility
-mode (see chapter 4).
-.xH 2 Including Other Makefiles
-.Ix 0 def makefile inclusion
-.Rd 2
-.LP
-Just as for programs, it is often useful to extract certain parts of a
-makefile into another file and just include it in other makefiles
-somehow. Many compilers allow you say something like
-.DS
-#include "defs.h"
-.DE
-to include the contents of
-.CW defs.h
-in the source file. PMake allows you to do the same thing for
-makefiles, with the added ability to use variables in the filenames.
-An include directive in a makefile looks either like this:
-.DS
-#include <file>
-.DE
-or this
-.DS
-#include "file"
-.DE
-The difference between the two is where PMake searches for the file:
-the first way, PMake will look for
-the file only in the system makefile directory (or directories)
-(to find out what that directory is, give PMake the
-.B \-h
-flag).
-.Ix 0 ref flags -h
-The system makefile directory search path can be overridden via the
-.B \-m
-option.
-.Ix 0 ref flags -m
-For files in double-quotes, the search is more complex:
-.RS
-.IP 1)
-The directory of the makefile that's including the file.
-.IP 2)
-The current directory (the one in which you invoked PMake).
-.IP 3)
-The directories given by you using
-.B \-I
-flags, in the order in which you gave them.
-.IP 4)
-Directories given by
-.CW .PATH
-dependency lines (see chapter 4).
-.IP 5)
-The system makefile directory.
-.RE
-.LP
-in that order.
-.LP
-You are free to use PMake variables in the filename\*-PMake will
-expand them before searching for the file. You must specify the
-searching method with either angle brackets or double-quotes
-.I outside
-of a variable expansion. I.e. the following
-.DS
-SYSTEM = <command.mk>
-
-#include $(SYSTEM)
-.DE
-won't work.
-.xH 2 Saving Commands
-.LP
-.Ix 0 def ...
-There may come a time when you will want to save certain commands to
-be executed when everything else is done. For instance: you're
-making several different libraries at one time and you want to create the
-members in parallel. Problem is,
-.CW ranlib
-is another one of those programs that can't be run more than once in
-the same directory at the same time (each one creates a file called
-.CW __.SYMDEF
-into which it stuffs information for the linker to use. Two of them
-running at once will overwrite each other's file and the result will
-be garbage for both parties). You might want a way to save the ranlib
-commands til the end so they can be run one after the other, thus
-keeping them from trashing each other's file. PMake allows you to do
-this by inserting an ellipsis (``.\|.\|.'') as a command between
-commands to be run at once and those to be run later.
-.LP
-So for the
-.CW ranlib
-case above, you might do this:
-.Rd 5
-.DS
-lib1.a          : $(LIB1OBJS)
-        rm -f $(.TARGET)
-        ar cr $(.TARGET) $(.ALLSRC)
-        ...
-        ranlib $(.TARGET)
-
-lib2.a          : $(LIB2OBJS)
-        rm -f $(.TARGET)
-        ar cr $(.TARGET) $(.ALLSRC)
-        ...
-        ranlib $(.TARGET)
-.DE
-.Ix 0 ref variable local .TARGET
-.Ix 0 ref variable local .ALLSRC
-This would save both
-.DS
-ranlib $(.TARGET)
-.DE
-commands until the end, when they would run one after the other
-(using the correct value for the
-.CW .TARGET
-variable, of course).
-.LP
-Commands saved in this manner are only executed if PMake manages to
-re-create everything without an error.
-.xH 2 Target Attributes
-.LP
-PMake allows you to give attributes to targets by means of special
-sources. Like everything else PMake uses, these sources begin with a
-period and are made up of all upper-case letters. There are various
-reasons for using them, and I will try to give examples for most of
-them. Others you'll have to find uses for yourself. Think of it as ``an
-exercise for the reader.'' By placing one (or more) of these as a source on a
-dependency line, you are ``marking the target(s) with that
-attribute.'' That's just the way I phrase it, so you know.
-.LP
-Any attributes given as sources for a transformation rule are applied
-to the target of the transformation rule when the rule is applied.
-.Ix 0 def attributes
-.Ix 0 ref source
-.Ix 0 ref target
-.nr pw 12
-.IP .DONTCARE \n(pw
-.Ix 0 def attributes .DONTCARE
-.Ix 0 def .DONTCARE
-If a target is marked with this attribute and PMake can't figure out
-how to create it, it will ignore this fact and assume the file isn't
-really needed or actually exists and PMake just can't find it. This may prove
-wrong, but the error will be noted later on, not when PMake tries to create
-the target so marked. This attribute also prevents PMake from
-attempting to touch the target if it is given the
-.B \-t
-flag.
-.Ix 0 ref flags -t
-.IP .EXEC \n(pw
-.Ix 0 def attributes .EXEC
-.Ix 0 def .EXEC
-This attribute causes its shell script to be executed while having no
-effect on targets that depend on it. This makes the target into a sort
-of subroutine.  An example. Say you have some LISP files that need to
-be compiled and loaded into a LISP process. To do this, you echo LISP
-commands into a file and execute a LISP with this file as its input
-when everything's done. Say also that you have to load other files
-from another system before you can compile your files and further,
-that you don't want to go through the loading and dumping unless one
-of
-.I your
-files has changed. Your makefile might look a little bit
-like this (remember, this is an educational example, and don't worry
-about the
-.CW COMPILE
-rule, all will soon become clear, grasshopper):
-.DS
-system          : init a.fasl b.fasl c.fasl
-        for i in $(.ALLSRC);
-        do
-                echo -n '(load "' >> input
-                echo -n ${i} >> input
-                echo '")' >> input
-        done
-        echo '(dump "$(.TARGET)")' >> input
-        lisp < input
-
-a.fasl          : a.l init COMPILE
-b.fasl          : b.l init COMPILE
-c.fasl          : c.l init COMPILE
-COMPILE         : .USE
-        echo '(compile "$(.ALLSRC)")' >> input
-init            : .EXEC
-        echo '(load-system)' > input
-.DE
-.Ix 0 ref .USE
-.Ix 0 ref attributes .USE
-.Ix 0 ref variable local .ALLSRC
-.IP "\&"
-.CW .EXEC
-sources, don't appear in the local variables of targets that depend on
-them (nor are they touched if PMake is given the
-.B \-t
-flag).
-.Ix 0 ref flags -t
-Note that all the rules, not just that for
-.CW system ,
-include
-.CW init
-as a source. This is because none of the other targets can be made
-until
-.CW init
-has been made, thus they depend on it.
-.IP .EXPORT \n(pw
-.Ix 0 def attributes .EXPORT
-.Ix 0 def .EXPORT
-This is used to mark those targets whose creation should be sent to
-another machine if at all possible. This may be used by some
-exportation schemes if the exportation is expensive. You should ask
-your system administrator if it is necessary.
-.IP .EXPORTSAME \n(pw
-.Ix 0 def attributes .EXPORTSAME
-.Ix 0 def .EXPORTSAME
-Tells the export system that the job should be exported to a machine
-of the same architecture as the current one. Certain operations (e.g.
-running text through
-.CW nroff )
-can be performed the same on any architecture (CPU and
-operating system type), while others (e.g. compiling a program with
-.CW cc )
-must be performed on a machine with the same architecture. Not all
-export systems will support this attribute.
-.IP .IGNORE \n(pw
-.Ix 0 def attributes .IGNORE
-.Ix 0 def .IGNORE attribute
-Giving a target the
-.CW .IGNORE
-attribute causes PMake to ignore errors from any of the target's commands, as
-if they all had `\-' before them.
-.IP .INVISIBLE \n(pw
-.Ix 0 def attributes .INVISIBLE
-.Ix 0 def .INVISIBLE
-This allows you to specify one target as a source for another without
-the one affecting the other's local variables. Useful if, say, you
-have a makefile that creates two programs, one of which is used to
-create the other, so it must exist before the other is created. You
-could say
-.DS
-prog1           : $(PROG1OBJS) prog2 MAKEINSTALL
-prog2           : $(PROG2OBJS) .INVISIBLE MAKEINSTALL
-.DE
-where
-.CW MAKEINSTALL
-is some complex .USE rule (see below) that depends on the
-.Ix 0 ref .USE
-.CW .ALLSRC
-variable containing the right things. Without the
-.CW .INVISIBLE
-attribute for
-.CW prog2 ,
-the
-.CW MAKEINSTALL
-rule couldn't be applied. This is not as useful as it should be, and
-the semantics may change (or the whole thing go away) in the
-not-too-distant future.
-.IP .JOIN \n(pw
-.Ix 0 def attributes .JOIN
-.Ix 0 def .JOIN
-This is another way to avoid performing some operations in parallel
-while permitting everything else to be done so. Specifically it
-forces the target's shell script to be executed only if one or more of the
-sources was out-of-date. In addition, the target's name,
-in both its
-.CW .TARGET
-variable and all the local variables of any target that depends on it,
-is replaced by the value of its
-.CW .ALLSRC
-variable.
-As an example, suppose you have a program that has four libraries that
-compile in the same directory along with, and at the same time as, the
-program. You again have the problem with
-.CW ranlib
-that I mentioned earlier, only this time it's more severe: you
-can't just put the ranlib off to the end since the program
-will need those libraries before it can be re-created. You can do
-something like this:
-.DS
-program         : $(OBJS) libraries
-        cc -o $(.TARGET) $(.ALLSRC)
-
-libraries       : lib1.a lib2.a lib3.a lib4.a .JOIN
-        ranlib $(.OODATE)
-.DE
-.Ix 0 ref variable local .TARGET
-.Ix 0 ref variable local .ALLSRC
-.Ix 0 ref variable local .OODATE
-.Ix 0 ref .TARGET
-.Ix 0 ref .ALLSRC
-.Ix 0 ref .OODATE
-In this case, PMake will re-create the
-.CW $(OBJS)
-as necessary, along with
-.CW lib1.a ,
-.CW lib2.a ,
-.CW lib3.a
-and
-.CW lib4.a .
-It will then execute
-.CW ranlib
-on any library that was changed and set
-.CW program 's
-.CW .ALLSRC
-variable to contain what's in
-.CW $(OBJS)
-followed by
-.CW "lib1.a lib2.a lib3.a lib4.a" .'' ``
-In case you're wondering, it's called
-.CW .JOIN
-because it joins together different threads of the ``input graph'' at
-the target marked with the attribute.
-Another aspect of the .JOIN attribute is it keeps the target from
-being created if the
-.B \-t
-flag was given.
-.Ix 0 ref flags -t
-.IP .MAKE \n(pw
-.Ix 0 def attributes .MAKE
-.Ix 0 def .MAKE
-The
-.CW .MAKE
-attribute marks its target as being a recursive invocation of PMake.
-This forces PMake to execute the script associated with the target (if
-it's out-of-date) even if you gave the
-.B \-n
-or
-.B \-t
-flag. By doing this, you can start at the top of a system and type
-.DS
-pmake -n
-.DE
-and have it descend the directory tree (if your makefiles are set up
-correctly), printing what it would have executed if you hadn't
-included the
-.B \-n
-flag.
-.IP .NOEXPORT \n(pw
-.Ix 0 def attributes .NOEXPORT
-.Ix 0 def .NOEXPORT attribute
-If possible, PMake will attempt to export the creation of all targets to
-another machine (this depends on how PMake was configured). Sometimes,
-the creation is so simple, it is pointless to send it to another
-machine. If you give the target the
-.CW .NOEXPORT
-attribute, it will be run locally, even if you've given PMake the
-.B "\-L 0"
-flag.
-.IP .NOTMAIN \n(pw
-.Ix 0 def attributes .NOTMAIN
-.Ix 0 def .NOTMAIN
-Normally, if you do not specify a target to make in any other way,
-PMake will take the first target on the first dependency line of a
-makefile as the target to create. That target is known as the ``Main
-Target'' and is labeled as such if you print the dependencies out
-using the
-.B \-p
-flag.
-.Ix 0 ref flags -p
-Giving a target this attribute tells PMake that the target is
-definitely
-.I not
-the Main Target.
-This allows you to place targets in an included makefile and
-have PMake create something else by default.
-.IP .PRECIOUS \n(pw
-.Ix 0 def attributes .PRECIOUS
-.Ix 0 def .PRECIOUS attribute
-When PMake is interrupted (you type control-C at the keyboard), it
-will attempt to clean up after itself by removing any half-made
-targets. If a target has the
-.CW .PRECIOUS
-attribute, however, PMake will leave it alone. An additional side
-effect of the `::' operator is to mark the targets as
-.CW .PRECIOUS .
-.Ix 0 ref operator double-colon
-.Ix 0 ref ::
-.IP .SILENT \n(pw
-.Ix 0 def attributes .SILENT
-.Ix 0 def .SILENT attribute
-Marking a target with this attribute keeps its commands from being
-printed when they're executed, just as if they had an `@' in front of them.
-.IP .USE \n(pw
-.Ix 0 def attributes .USE
-.Ix 0 def .USE
-By giving a target this attribute, you turn it into PMake's equivalent
-of a macro. When the target is used as a source for another target,
-the other target acquires the commands, sources and attributes (except
-.CW .USE )
-of the source.
-If the target already has commands, the
-.CW .USE
-target's commands are added to the end. If more than one .USE-marked
-source is given to a target, the rules are applied sequentially.
-.IP "\&" \n(pw
-The typical .USE rule (as I call them) will use the sources of the
-target to which it is applied (as stored in the
-.CW .ALLSRC
-variable for the target) as its ``arguments,'' if you will.
-For example, you probably noticed that the commands for creating
-.CW lib1.a
-and
-.CW lib2.a
-in the example in section 3.3
-.Rm 5 3.3
-were exactly the same. You can use the
-.CW .USE
-attribute to eliminate the repetition, like so:
-.DS
-lib1.a          : $(LIB1OBJS) MAKELIB
-lib2.a          : $(LIB2OBJS) MAKELIB
-
-MAKELIB         : .USE
-        rm -f $(.TARGET)
-        ar cr $(.TARGET) $(.ALLSRC)
-        ...
-        ranlib $(.TARGET)
-.DE
-.Ix 0 ref variable local .TARGET
-.Ix 0 ref variable local .ALLSRC
-.IP "\&" \n(pw
-Several system makefiles (not to be confused with The System Makefile)
-make use of these  .USE rules to make your
-life easier (they're in the default, system makefile directory...take a look).
-Note that the .USE rule source itself
-.CW MAKELIB ) (
-does not appear in any of the targets's local variables.
-There is no limit to the number of times I could use the
-.CW MAKELIB
-rule. If there were more libraries, I could continue with
-.CW "lib3.a : $(LIB3OBJS) MAKELIB" '' ``
-and so on and so forth.
-.xH 2 Special Targets
-.LP
-As there were in Make, so there are certain targets that have special
-meaning to PMake. When you use one on a dependency line, it is the
-only target that may appear on the left-hand-side of the operator.
-.Ix 0 ref target
-.Ix 0 ref operator
-As for the attributes and variables, all the special targets
-begin with a period and consist of upper-case letters only.
-I won't describe them all in detail because some of them are rather
-complex and I'll describe them in more detail than you'll want in
-chapter 4.
-The targets are as follows:
-.nr pw 10
-.IP .BEGIN \n(pw
-.Ix 0 def .BEGIN
-Any commands attached to this target are executed before anything else
-is done. You can use it for any initialization that needs doing.
-.IP .DEFAULT \n(pw
-.Ix 0 def .DEFAULT
-This is sort of a .USE rule for any target (that was used only as a
-source) that PMake can't figure out any other way to create. It's only
-``sort of'' a .USE rule because only the shell script attached to the
-.CW .DEFAULT
-target is used. The
-.CW .IMPSRC
-variable of a target that inherits
-.CW .DEFAULT 's
-commands is set to the target's own name.
-.Ix 0 ref .IMPSRC
-.Ix 0 ref variable local .IMPSRC
-.IP .END \n(pw
-.Ix 0 def .END
-This serves a function similar to
-.CW .BEGIN ,
-in that commands attached to it are executed once everything has been
-re-created (so long as no errors occurred). It also serves the extra
-function of being a place on which PMake can hang commands you put off
-to the end. Thus the script for this target will be executed before
-any of the commands you save with the ``.\|.\|.''.
-.Ix 0 ref ...
-.IP .EXPORT \n(pw
-The sources for this target are passed to the exportation system compiled
-into PMake. Some systems will use these sources to configure
-themselves. You should ask your system administrator about this.
-.IP .IGNORE \n(pw
-.Ix 0 def .IGNORE target
-.Ix 0 ref .IGNORE attribute
-.Ix 0 ref attributes .IGNORE
-This target marks each of its sources with the
-.CW .IGNORE
-attribute. If you don't give it any sources, then it is like
-giving the
-.B \-i
-flag when you invoke PMake \*- errors are ignored for all commands.
-.Ix 0 ref flags -i
-.IP .INCLUDES \n(pw
-.Ix 0 def .INCLUDES target
-.Ix 0 def variable global .INCLUDES
-.Ix 0 def .INCLUDES variable
-The sources for this target are taken to be suffixes that indicate a
-file that can be included in a program source file.
-The suffix must have already been declared with
-.CW .SUFFIXES
-(see below).
-Any suffix so marked will have the directories on its search path
-(see
-.CW .PATH ,
-below) placed in the
-.CW .INCLUDES
-variable, each preceded by a
-.B \-I
-flag. This variable can then be used as an argument for the compiler
-in the normal fashion. The
-.CW .h
-suffix is already marked in this way in the system makefile.
-.Ix 0 ref makefilesystem
-E.g. if you have
-.DS
-\&.SUFFIXES       : .bitmap
-\&.PATH.bitmap    : /usr/local/X/lib/bitmaps
-\&.INCLUDES       : .bitmap
-.DE
-PMake will place
-.CW "-I/usr/local/X/lib/bitmaps" '' ``
-in the
-.CW .INCLUDES
-variable and you can then say
-.DS
-cc $(.INCLUDES) -c xprogram.c
-.DE
-(Note: the
-.CW .INCLUDES
-variable is not actually filled in until the entire makefile has been read.)
-.IP .INTERRUPT \n(pw
-.Ix 0 def .INTERRUPT
-When PMake is interrupted,
-it will execute the commands in the script for this target, if it
-exists.
-.IP .LIBS \n(pw
-.Ix 0 def .LIBS target
-.Ix 0 def .LIBS variable
-.Ix 0 def variable global .LIBS
-This does for libraries what
-.CW .INCLUDES
-does for include files, except the flag used is
-.B \-L ,
-as required by those linkers that allow you to tell them where to find
-libraries. The variable used is
-.CW .LIBS .
-Be forewarned that PMake may not have been compiled to do this if the
-linker on your system doesn't accept the
-.B \-L
-flag, though the
-.CW .LIBS
-variable will always be defined once the makefile has been read.
-.IP .MAIN \n(pw
-.Ix 0 def .MAIN
-If you didn't give a target (or targets) to create when you invoked
-PMake, it will take the sources of this target as the targets to
-create.
-.IP .MAKEFLAGS \n(pw
-.Ix 0 def .MAKEFLAGS target
-This target provides a way for you to always specify flags for PMake
-when the makefile is used. The flags are just as they would be typed
-to the shell (except you can't use shell variables unless they're in
-the environment),
-though the
-.B \-f
-and
-.B \-r
-flags have no effect.
-.IP .NULL \n(pw
-.Ix 0 def .NULL
-.Ix 0 ref suffix null
-.Ix 0 ref "null suffix"
-This allows you to specify what suffix PMake should pretend a file has
-if, in fact, it has no known suffix. Only one suffix may be so
-designated. The last source on the dependency line is the suffix that
-is used (you should, however, only give one suffix.\|.\|.).
-.IP .PATH \n(pw
-.Ix 0 def .PATH
-If you give sources for this target, PMake will take them as
-directories in which to search for files it cannot find in the current
-directory. If you give no sources, it will clear out any directories
-added to the search path before. Since the effects of this all get
-very complex, I'll leave it til chapter four to give you a complete
-explanation.
-.IP .PATH\fIsuffix\fP \n(pw
-.Ix 0 ref .PATH
-This does a similar thing to
-.CW .PATH ,
-but it does it only for files with the given suffix. The suffix must
-have been defined already. Look at
-.B "Search Paths"
-(section 4.1)
-.Rm 6 4.1
-for more information.
-.IP .PRECIOUS \n(pw
-.Ix 0 def .PRECIOUS target
-.Ix 0 ref .PRECIOUS attribute
-.Ix 0 ref attributes .PRECIOUS
-Similar to
-.CW .IGNORE ,
-this gives the
-.CW .PRECIOUS
-attribute to each source on the dependency line, unless there are no
-sources, in which case the
-.CW .PRECIOUS
-attribute is given to every target in the file.
-.IP .RECURSIVE \n(pw
-.Ix 0 def .RECURSIVE
-.Ix 0 ref attributes .MAKE
-.Ix 0 ref .MAKE
-This target applies the
-.CW .MAKE
-attribute to all its sources. It does nothing if you don't give it any sources.
-.IP .SHELL \n(pw
-.Ix 0 def .SHELL
-PMake is not constrained to only using the Bourne shell to execute
-the commands you put in the makefile. You can tell it some other shell
-to use with this target. Check out
-.B "A Shell is a Shell is a Shell"
-(section 4.4)
-.Rm 7 4.4
-for more information.
-.IP .SILENT \n(pw
-.Ix 0 def .SILENT target
-.Ix 0 ref .SILENT attribute
-.Ix 0 ref attributes .SILENT
-When you use
-.CW .SILENT
-as a target, it applies the
-.CW .SILENT
-attribute to each of its sources. If there are no sources on the
-dependency line, then it is as if you gave PMake the
-.B \-s
-flag and no commands will be echoed.
-.IP .SUFFIXES \n(pw
-.Ix 0 def .SUFFIXES
-This is used to give new file suffixes for PMake to handle. Each
-source is a suffix PMake should recognize. If you give a
-.CW .SUFFIXES
-dependency line with no sources, PMake will forget about all the
-suffixes it knew (this also nukes the null suffix).
-For those targets that need to have suffixes defined, this is how you do it.
-.LP
-In addition to these targets, a line of the form
-.DS
-\fIattribute\fP : \fIsources\fP
-.DE
-applies the
-.I attribute
-to all the targets listed as
-.I sources .
-.xH 2 Modifying Variable Expansion
-.LP
-.Ix 0 def variable expansion modified
-.Ix 0 ref variable expansion
-.Ix 0 def variable modifiers
-Variables need not always be expanded verbatim. PMake defines several
-modifiers that may be applied to a variable's value before it is
-expanded. You apply a modifier by placing it after the variable name
-with a colon between the two, like so:
-.DS
-${\fIVARIABLE\fP:\fImodifier\fP}
-.DE
-Each modifier is a single character followed by something specific to
-the modifier itself.
-You may apply as many modifiers as you want \*- each one is applied to
-the result of the previous and is separated from the previous by
-another colon.
-.LP
-There are seven ways to modify a variable's expansion, most of which
-come from the C shell variable modification characters:
-.RS
-.IP "M\fIpattern\fP"
-.Ix 0 def :M
-.Ix 0 def modifier match
-This is used to select only those words (a word is a series of
-characters that are neither spaces nor tabs) that match the given
-.I pattern .
-The pattern is a wildcard pattern like that used by the shell, where
-.CW *
-means 0 or more characters of any sort;
-.CW ?
-is any single character;
-.CW [abcd]
-matches any single character that is either `a', `b', `c' or `d'
-(there may be any number of characters between the brackets);
-.CW [0-9]
-matches any single character that is between `0' and `9' (i.e. any
-digit. This form may be freely mixed with the other bracket form), and
-`\\' is used to escape any of the characters `*', `?', `[' or `:',
-leaving them as regular characters to match themselves in a word.
-For example, the system makefile
-.CW <makedepend.mk>
-uses
-.CW "$(CFLAGS:M-[ID]*)" '' ``
-to extract all the
-.CW \-I
-and
-.CW \-D
-flags that would be passed to the C compiler. This allows it to
-properly locate include files and generate the correct dependencies.
-.IP "N\fIpattern\fP"
-.Ix 0 def :N
-.Ix 0 def modifier nomatch
-This is identical to
-.CW :M
-except it substitutes all words that don't match the given pattern.
-.IP "S/\fIsearch-string\fP/\fIreplacement-string\fP/[g]"
-.Ix 0 def :S
-.Ix 0 def modifier substitute
-Causes the first occurrence of
-.I search-string
-in the variable to be replaced by
-.I replacement-string ,
-unless the
-.CW g
-flag is given at the end, in which case all occurrences of the string
-are replaced. The substitution is performed on each word in the
-variable in turn. If 
-.I search-string
-begins with a
-.CW ^ ,
-the string must match starting at the beginning of the word. If
-.I search-string
-ends with a
-.CW $ ,
-the string must match to the end of the word (these two may be
-combined to force an exact match). If a backslash precedes these two
-characters, however, they lose their special meaning. Variable
-expansion also occurs in the normal fashion inside both the
-.I search-string
-and the
-.I replacement-string ,
-.B except
-that a backslash is used to prevent the expansion of a
-.CW $ ,
-not another dollar sign, as is usual.
-Note that
-.I search-string
-is just a string, not a pattern, so none of the usual
-regular-expression/wildcard characters have any special meaning save
-.CW ^
-and
-.CW $ .
-In the replacement string,
-the
-.CW &
-character is replaced by the
-.I search-string
-unless it is preceded by a backslash.
-You are allowed to use any character except
-colon or exclamation point to separate the two strings. This so-called
-delimiter character may be placed in either string by preceding it
-with a backslash.
-.IP T
-.Ix 0 def :T
-.Ix 0 def modifier tail
-Replaces each word in the variable expansion by its last
-component (its ``tail''). For example, given
-.DS
-OBJS = ../lib/a.o b /usr/lib/libm.a
-TAILS = $(OBJS:T)
-.DE
-the variable
-.CW TAILS
-would expand to
-.CW "a.o b libm.a" .'' ``
-.IP H
-.Ix 0 def :H
-.Ix 0 def modifier head
-This is similar to
-.CW :T ,
-except that every word is replaced by everything but the tail (the
-``head''). Using the same definition of
-.CW OBJS ,
-the string
-.CW "$(OBJS:H)" '' ``
-would expand to
-.CW "../lib /usr/lib" .'' ``
-Note that the final slash on the heads is removed and
-anything without a head is replaced by the empty string.
-.IP E
-.Ix 0 def :E
-.Ix 0 def modifier extension
-.Ix 0 def modifier suffix
-.Ix 0 ref suffix "variable modifier"
-.CW :E
-replaces each word by its suffix (``extension''). So
-.CW "$(OBJS:E)" '' ``
-would give you
-.CW ".o .a" .'' ``
-.IP R
-.Ix 0 def :R
-.Ix 0 def modifier root
-.Ix 0 def modifier base
-This replaces each word by everything but the suffix (the ``root'' of
-the word).
-.CW "$(OBJS:R)" '' ``
-expands to ``
-.CW "../lib/a b /usr/lib/libm" .''
-.RE
-.LP
-In addition, the System V style of substitution is also supported.
-This looks like:
-.DS
-$(\fIVARIABLE\fP:\fIsearch-string\fP=\fIreplacement\fP)
-.DE
-It must be the last modifier in the chain. The search is anchored at
-the end of each word, so only suffixes or whole words may be replaced.
-.xH 2 More on Debugging
-.xH 2 More Exercises
-.IP (3.1)
-You've got a set programs, each of which is created from its own
-assembly-language source file (suffix
-.CW .asm ).
-Each program can be assembled into two versions, one with error-checking
-code assembled in and one without. You could assemble them into files
-with different suffixes
-.CW .eobj \& (
-and
-.CW .obj ,
-for instance), but your linker only understands files that end in
-.CW .obj .
-To top it all off, the final executables
-.I must
-have the suffix
-.CW .exe .
-How can you still use transformation rules to make your life easier
-(Hint: assume the error-checking versions have
-.CW ec
-tacked onto their prefix)?
-.IP (3.2)
-Assume, for a moment or two, you want to perform a sort of
-``indirection'' by placing the name of a variable into another one,
-then you want to get the value of the first by expanding the second
-somehow. Unfortunately, PMake doesn't allow constructs like
-.DS I
-$($(FOO))
-.DE
-What do you do? Hint: no further variable expansion is performed after
-modifiers are applied, thus if you cause a $ to occur in the
-expansion, that's what will be in the result.
-.xH 1 PMake for Gods
-.LP
-This chapter is devoted to those facilities in PMake that allow you to
-do a great deal in a makefile with very little work, as well as do
-some things you couldn't do in Make without a great deal of work (and
-perhaps the use of other programs). The problem with these features,
-is they must be handled with care, or you will end up with a mess.
-.LP
-Once more, I assume a greater familiarity with
-.UX
-or Sprite than I did in the previous two chapters.
-.xH 2 Search Paths
-.Rd 6
-.LP
-PMake supports the dispersal of files into multiple directories by
-allowing you to specify places to look for sources with
-.CW .PATH
-targets in the makefile. The directories you give as sources for these
-targets make up a ``search path.'' Only those files used exclusively
-as sources are actually sought on a search path, the assumption being
-that anything listed as a target in the makefile can be created by the
-makefile and thus should be in the current directory.
-.LP
-There are two types of search paths
-in PMake: one is used for all types of files (including included
-makefiles) and is specified with a plain
-.CW .PATH
-target (e.g.
-.CW ".PATH : RCS" ''), ``
-while the other is specific to a certain type of file, as indicated by
-the file's suffix. A specific search path is indicated by immediately following
-the
-.CW .PATH
-with the suffix of the file. For instance
-.DS
-\&.PATH.h         : /sprite/lib/include /sprite/att/lib/include
-.DE
-would tell PMake to look in the directories
-.CW /sprite/lib/include
-and
-.CW /sprite/att/lib/include
-for any files whose suffix is
-.CW .h .
-.LP
-The current directory is always consulted first to see if a file
-exists. Only if it cannot be found there are the directories in the
-specific search path, followed by those in the general search path,
-consulted.
-.LP
-A search path is also used when expanding wildcard characters. If the
-pattern has a recognizable suffix on it, the path for that suffix will
-be used for the expansion. Otherwise the default search path is employed.
-.LP
-When a file is found in some directory other than the current one, all
-local variables that would have contained the target's name
-.CW .ALLSRC , (
-and
-.CW .IMPSRC )
-will instead contain the path to the file, as found by PMake.
-Thus if you have a file
-.CW ../lib/mumble.c
-and a makefile
-.DS
-\&.PATH.c         : ../lib
-mumble          : mumble.c
-        $(CC) -o $(.TARGET) $(.ALLSRC)
-.DE
-the command executed to create
-.CW mumble
-would be
-.CW "cc -o mumble ../lib/mumble.c" .'' ``
-(As an aside, the command in this case isn't strictly necessary, since
-it will be found using transformation rules if it isn't given. This is because
-.CW .out
-is the null suffix by default and a transformation exists from
-.CW .c
-to
-.CW .out .
-Just thought I'd throw that in.)
-.LP
-If a file exists in two directories on the same search path, the file
-in the first directory on the path will be the one PMake uses. So if
-you have a large system spread over many directories, it would behoove
-you to follow a naming convention that avoids such conflicts.
-.LP
-Something you should know about the way search paths are implemented
-is that each directory is read, and its contents cached, exactly once
-\&\*- when it is first encountered \*- so any changes to the
-directories while PMake is running will not be noted when searching
-for implicit sources, nor will they be found when PMake attempts to
-discover when the file was last modified, unless the file was created in the
-current directory. While people have suggested that PMake should read
-the directories each time, my experience suggests that the caching seldom
-causes problems. In addition, not caching the directories slows things
-down enormously because of PMake's attempts to apply transformation
-rules through non-existent files \*- the number of extra file-system
-searches is truly staggering, especially if many files without
-suffixes are used and the null suffix isn't changed from
-.CW .out .
-.xH 2 Archives and Libraries
-.LP
-.UX
-and Sprite allow you to merge files into an archive using the
-.CW ar
-command. Further, if the files are relocatable object files, you can
-run
-.CW ranlib
-on the archive and get yourself a library that you can link into any
-program you want. The main problem with archives is they double the
-space you need to store the archived files, since there's one copy in
-the archive and one copy out by itself. The problem with libraries is
-you usually think of them as
-.CW -lm
-rather than
-.CW /usr/lib/libm.a
-and the linker thinks they're out-of-date if you so much as look at
-them.
-.LP
-PMake solves the problem with archives by allowing you to tell it to
-examine the files in the archives (so you can remove the individual
-files without having to regenerate them later). To handle the problem
-with libraries, PMake adds an additional way of deciding if a library
-is out-of-date:
-.IP \(bu 2
-If the table of contents is older than the library, or is missing, the
-library is out-of-date.
-.LP
-A library is any target that looks like
-.CW \-l name'' ``
-or that ends in a suffix that was marked as a library using the
-.CW .LIBS
-target.
-.CW .a
-is so marked in the system makefile.
-.LP
-Members of an archive are specified as
-``\fIarchive\fP(\fImember\fP[ \fImember\fP...])''.
-Thus
-.CW libdix.a(window.o) '' ``'
-specifies the file
-.CW window.o
-in the archive
-.CW libdix.a .
-You may also use wildcards to specify the members of the archive. Just
-remember that most the wildcard characters will only find 
-.I existing
-files.
-.LP
-A file that is a member of an archive is treated specially. If the
-file doesn't exist, but it is in the archive, the modification time
-recorded in the archive is used for the file when determining if the
-file is out-of-date. When figuring out how to make an archived member target
-(not the file itself, but the file in the archive \*- the
-\fIarchive\fP(\fImember\fP) target), special care is
-taken with the transformation rules, as follows:
-.IP \(bu 2
-\&\fIarchive\fP(\fImember\fP) is made to depend on \fImember\fP.
-.IP \(bu 2
-The transformation from the \fImember\fP's suffix to the
-\fIarchive\fP's suffix is applied to the \fIarchive\fP(\fImember\fP) target.
-.IP \(bu 2
-The \fIarchive\fP(\fImember\fP)'s
-.CW .TARGET
-variable is set to the name of the \fImember\fP if \fImember\fP is
-actually a target, or the path to the member file if \fImember\fP is
-only a source.
-.IP \(bu 2
-The
-.CW .ARCHIVE
-variable for the \fIarchive\fP(\fImember\fP) target is set to the name
-of the \fIarchive\fP.
-.Ix 0 def variable local .ARCHIVE
-.Ix 0 def .ARCHIVE
-.IP \(bu 2
-The
-.CW .MEMBER
-variable is set to the actual string inside the parentheses. In most
-cases, this will be the same as the
-.CW .TARGET
-variable.
-.Ix 0 def variable local .MEMBER
-.Ix 0 def .MEMBER
-.IP \(bu 2
-The \fIarchive\fP(\fImember\fP)'s place in the local variables of the
-targets that depend on it is taken by the value of its
-.CW .TARGET
-variable.
-.LP
-Thus, a program library could be created with the following makefile:
-.DS
-\&.o.a            :
-        ...
-        rm -f $(.TARGET:T)
-OBJS            = obj1.o obj2.o obj3.o
-libprog.a       : libprog.a($(OBJS))
-        ar cru $(.TARGET) $(.OODATE)
-        ranlib $(.TARGET)
-.DE
-This will cause the three object files to be compiled (if the
-corresponding source files were modified after the object file or, if
-that doesn't exist, the archived object file), the out-of-date ones
-archived in
-.CW libprog.a ,
-a table of contents placed in the archive and the newly-archived
-object files to be removed.
-.LP
-All this is used in the 
-.CW makelib.mk
-system makefile to create a single library with ease. This makefile
-looks like this:
-.DS
-.SM
-#
-# Rules for making libraries. The object files that make up the library
-# are removed once they are archived.
-#
-# To make several libraries in parallel, you should define the variable
-# "many_libraries". This will serialize the invocations of ranlib.
-#
-# To use, do something like this:
-#
-# OBJECTS = <files in the library>
-#
-# fish.a: fish.a($(OBJECTS)) MAKELIB
-#
-#
-
-#ifndef _MAKELIB_MK
-_MAKELIB_MK    =
-
-#include       <po.mk>
-
-\&.po.a .o.a   :
-       ...
-       rm -f $(.MEMBER)
-
-ARFLAGS                ?= crl
-
-#
-# Re-archive the out-of-date members and recreate the library's table of
-# contents using ranlib. If many_libraries is defined, put the ranlib
-# off til the end so many libraries can be made at once.
-#
-MAKELIB                : .USE .PRECIOUS
-       ar $(ARFLAGS) $(.TARGET) $(.OODATE)
-#ifndef no_ranlib
-# ifdef many_libraries
-       ...
-# endif many_libraries
-       ranlib $(.TARGET)
-#endif no_ranlib
-
-#endif _MAKELIB_MK
-.DE
-.xH 2 On the Condition...
-.Rd 1
-.LP
-Like the C compiler before it, PMake allows you to configure the makefile,
-based on the current environment, using conditional statements. A
-conditional looks like this:
-.DS
-#if \fIboolean expression\fP
-\fIlines\fP
-#elif \fIanother boolean expression\fP
-\fImore lines\fP
-#else
-\fIstill more lines\fP
-#endif
-.DE
-They may be nested to a maximum depth of 30 and may occur anywhere
-(except in a comment, of course). The
-.CW # '' ``
-must the very first character on the line.
-.LP
-Each
-.I "boolean expression"
-is made up of terms that look like function calls, the standard C
-boolean operators
-.CW && ,
-.CW || ,
-and
-.CW ! ,
-and the standard relational operators
-.CW == ,
-.CW != ,
-.CW > ,
-.CW >= ,
-.CW < ,
-and
-.CW <= ,
-with
-.CW ==
-and
-.CW !=
-being overloaded to allow string comparisons as well.
-.CW &&
-represents logical AND;
-.CW ||
-is logical OR and
-.CW !
-is logical NOT.  The arithmetic and string operators take precedence
-over all three of these operators, while NOT takes precedence over
-AND, which takes precedence over OR.  This precedence may be
-overridden with parentheses, and an expression may be parenthesized to
-your heart's content.  Each term looks like a call on one of four
-functions:
-.nr pw 9
-.Ix 0 def make
-.Ix 0 def conditional make
-.Ix 0 def if make
-.IP make \n(pw
-The syntax is
-.CW make( \fItarget\fP\c
-.CW )
-where
-.I target
-is a target in the makefile. This is true if the given target was
-specified on the command line, or as the source for a
-.CW .MAIN
-target (note that the sources for
-.CW .MAIN
-are only used if no targets were given on the command line).
-.IP defined \n(pw
-.Ix 0 def defined
-.Ix 0 def conditional defined
-.Ix 0 def if defined
-The syntax is
-.CW defined( \fIvariable\fP\c
-.CW )
-and is true if
-.I variable
-is defined. Certain variables are defined in the system makefile that
-identify the system on which PMake is being run.
-.IP exists \n(pw
-.Ix 0 def exists
-.Ix 0 def conditional exists
-.Ix 0 def if exists
-The syntax is
-.CW exists( \fIfile\fP\c
-.CW )
-and is true if the file can be found on the global search path (i.e.
-that defined by
-.CW .PATH
-targets, not by
-.CW .PATH \fIsuffix\fP
-targets).
-.IP empty \n(pw
-.Ix 0 def empty
-.Ix 0 def conditional empty
-.Ix 0 def if empty
-This syntax is much like the others, except the string inside the
-parentheses is of the same form as you would put between parentheses
-when expanding a variable, complete with modifiers and everything. The
-function returns true if the resulting string is empty (NOTE: an undefined
-variable in this context will cause at the very least a warning
-message about a malformed conditional, and at the worst will cause the
-process to stop once it has read the makefile. If you want to check
-for a variable being defined or empty, use the expression
-.CW !defined( \fIvar\fP\c ``
-.CW ") || empty(" \fIvar\fP\c
-.CW ) ''
-as the definition of
-.CW ||
-will prevent the
-.CW empty()
-from being evaluated and causing an error, if the variable is
-undefined). This can be used to see if a variable contains a given
-word, for example:
-.DS
-#if !empty(\fIvar\fP:M\fIword\fP)
-.DE
-.LP
-The arithmetic and string operators may only be used to test the value
-of a variable. The lefthand side must contain the variable expansion,
-while the righthand side contains either a string, enclosed in
-double-quotes, or a number. The standard C numeric conventions (except
-for specifying an octal number) apply to both sides. E.g.
-.DS
-#if $(OS) == 4.3
-
-#if $(MACHINE) == "sun3"
-
-#if $(LOAD_ADDR) < 0xc000
-.DE
-are all valid conditionals. In addition, the numeric value of a
-variable can be tested as a boolean as follows:
-.DS
-#if $(LOAD)
-.DE
-would see if
-.CW LOAD
-contains a non-zero value and
-.DS
-#if !$(LOAD)
-.DE
-would test if
-.CW LOAD
-contains a zero value.
-.LP
-In addition to the bare
-.CW #if ,'' ``
-there are other forms that apply one of the first two functions to each
-term. They are as follows:
-.DS
-       ifdef   \fRdefined\fP
-       ifndef  \fR!defined\fP
-       ifmake  \fRmake\fP
-       ifnmake \fR!make\fP
-.DE
-There are also the ``else if'' forms:
-.CW elif ,
-.CW elifdef ,
-.CW elifndef ,
-.CW elifmake ,
-and
-.CW elifnmake .
-.LP
-For instance, if you wish to create two versions of a program, one of which
-is optimized (the production version) and the other of which is for debugging
-(has symbols for dbx), you have two choices: you can create two
-makefiles, one of which uses the
-.CW \-g
-flag for the compilation, while the other uses the
-.CW \-O
-flag, or you can use another target (call it
-.CW debug )
-to create the debug version. The construct below will take care of
-this for you. I have also made it so defining the variable
-.CW DEBUG
-(say with
-.CW "pmake -D DEBUG" )
-will also cause the debug version to be made.
-.DS
-#if defined(DEBUG) || make(debug)
-CFLAGS         += -g
-#else
-CFLAGS         += -O
-#endif
-.DE
-There are, of course, problems with this approach. The most glaring
-annoyance is that if you want to go from making a debug version to
-making a production version, you have to remove all the object files,
-or you will get some optimized and some debug versions in the same
-program. Another annoyance is you have to be careful not to make two
-targets that ``conflict'' because of some conditionals in the
-makefile. For instance
-.DS
-#if make(print)
-FORMATTER      = ditroff -Plaser_printer
-#endif
-#if make(draft)
-FORMATTER      = nroff -Pdot_matrix_printer
-#endif
-.DE
-would wreak havoc if you tried
-.CW "pmake draft print" '' ``
-since you would use the same formatter for each target. As I said,
-this all gets somewhat complicated.
-.xH 2 A Shell is a Shell is a Shell
-.Rd 7
-.LP
-In normal operation, the Bourne Shell (better known as
-.CW sh '') ``
-is used to execute the commands to re-create targets. PMake also allows you
-to specify a different shell for it to use when executing these
-commands. There are several things PMake must know about the shell you
-wish to use. These things are specified as the sources for the
-.CW .SHELL
-.Ix 0 ref .SHELL
-.Ix 0 ref target .SHELL
-target by keyword, as follows:
-.IP "\fBpath=\fP\fIpath\fP"
-PMake needs to know where the shell actually resides, so it can
-execute it. If you specify this and nothing else, PMake will use the
-last component of the path and look in its table of the shells it
-knows and use the specification it finds, if any. Use this if you just
-want to use a different version of the Bourne or C Shell (yes, PMake knows
-how to use the C Shell too).
-.IP "\fBname=\fP\fIname\fP"
-This is the name by which the shell is to be known. It is a single
-word and, if no other keywords are specified (other than
-.B path ),
-it is the name by which PMake attempts to find a specification for
-it (as mentioned above). You can use this if you would just rather use
-the C Shell than the Bourne Shell
-.CW ".SHELL: name=csh" '' (``
-will do it).
-.IP "\fBquiet=\fP\fIecho-off command\fP"
-As mentioned before, PMake actually controls whether commands are
-printed by introducing commands into the shell's input stream. This
-keyword, and the next two, control what those commands are. The
-.B quiet
-keyword is the command used to turn echoing off. Once it is turned
-off, echoing is expected to remain off until the echo-on command is given.
-.IP "\fBecho=\fP\fIecho-on command\fP"
-The command PMake should give to turn echoing back on again.
-.IP "\fBfilter=\fP\fIprinted echo-off command\fP"
-Many shells will echo the echo-off command when it is given. This
-keyword tells PMake in what format the shell actually prints the
-echo-off command. Wherever PMake sees this string in the shell's
-output, it will delete it and any following whitespace, up to and
-including the next newline. See the example at the end of this section
-for more details.
-.IP "\fBechoFlag=\fP\fIflag to turn echoing on\fP"
-Unless a target has been marked
-.CW .SILENT ,
-PMake wants to start the shell running with echoing on. To do this, it
-passes this flag to the shell as one of its arguments. If either this
-or the next flag begins with a `\-', the flags will be passed to the
-shell as separate arguments. Otherwise, the two will be concatenated
-(if they are used at the same time, of course).
-.IP "\fBerrFlag=\fP\fIflag to turn error checking on\fP"
-Likewise, unless a target is marked
-.CW .IGNORE ,
-PMake wishes error-checking to be on from the very start. To this end,
-it will pass this flag to the shell as an argument. The same rules for
-an initial `\-' apply as for the
-.B echoFlag .
-.IP "\fBcheck=\fP\fIcommand to turn error checking on\fP"
-Just as for echo-control, error-control is achieved by inserting
-commands into the shell's input stream. This is the command to make
-the shell check for errors. It also serves another purpose if the
-shell doesn't have error-control as commands, but I'll get into that
-in a minute. Again, once error checking has been turned on, it is
-expected to remain on until it is turned off again.
-.IP "\fBignore=\fP\fIcommand to turn error checking off\fP"
-This is the command PMake uses to turn error checking off. It has
-another use if the shell doesn't do error-control, but I'll tell you
-about that.\|.\|.\|now.
-.IP "\fBhasErrCtl=\fP\fIyes or no\fP"
-This takes a value that is either
-.B yes
-or
-.B no .
-Now you might think that the existence of the
-.B check
-and
-.B ignore
-keywords would be enough to tell PMake if the shell can do
-error-control, but you'd be wrong. If
-.B hasErrCtl
-is
-.B yes ,
-PMake uses the check and ignore commands in a straight-forward manner.
-If this is
-.B no ,
-however, their use is rather different. In this case, the check
-command is used as a template, in which the string
-.B %s
-is replaced by the command that's about to be executed, to produce a
-command for the shell that will echo the command to be executed. The
-ignore command is also used as a template, again with
-.B %s
-replaced by the command to be executed, to produce a command that will
-execute the command to be executed and ignore any error it returns.
-When these strings are used as templates, you must provide newline(s)
-.CW \en '') (``
-in the appropriate place(s).
-.LP
-The strings that follow these keywords may be enclosed in single or
-double quotes (the quotes will be stripped off) and may contain the
-usual C backslash-characters (\en is newline, \er is return, \eb is
-backspace, \e' escapes a single-quote inside single-quotes, \e"
-escapes a double-quote inside double-quotes). Now for an example.
-.LP
-This is actually the contents of the
-.CW <shx.mk>
-system makefile, and causes PMake to use the Bourne Shell in such a
-way that each command is printed as it is executed. That is, if more
-than one command is given on a line, each will be printed separately.
-Similarly, each time the body of a loop is executed, the commands
-within that loop will be printed, etc. The specification runs like
-this:
-.DS
-#
-# This is a shell specification to have the Bourne shell echo
-# the commands just before executing them, rather than when it reads
-# them. Useful if you want to see how variables are being expanded, etc.
-#
-\&.SHELL       : path=/bin/sh \e
-       quiet="set -" \e
-       echo="set -x" \e
-       filter="+ set - " \e
-       echoFlag=x \e
-       errFlag=e \e
-       hasErrCtl=yes \e
-       check="set -e" \e
-       ignore="set +e"
-.DE
-.LP
-It tells PMake the following:
-.Bp
-The shell is located in the file
-.CW /bin/sh .
-It need not tell PMake that the name of the shell is
-.CW sh 
-as PMake can figure that out for itself (it's the last component of
-the path).
-.Bp
-The command to stop echoing is
-.CW "set -" .
-.Bp
-The command to start echoing is
-.CW "set -x" .
-.Bp
-When the echo off command is executed, the shell will print
-.CW "+ set - " 
-(The `+' comes from using the
-.CW \-x
-flag (rather than the
-.CW \-v
-flag PMake usually uses)). PMake will remove all occurrences of this
-string from the output, so you don't notice extra commands you didn't
-put there.
-.Bp
-The flag the Bourne Shell will take to start echoing in this way is
-the
-.CW \-x
-flag. The Bourne Shell will only take its flag arguments concatenated
-as its first argument, so neither this nor the
-.B errFlag
-specification begins with a \-.
-.Bp
-The flag to use to turn error-checking on from the start is
-.CW \-e .
-.Bp
-The shell can turn error-checking on and off, and the commands to do
-so are
-.CW "set +e"
-and
-.CW "set -e" ,
-respectively.
-.LP
-I should note that this specification is for Bourne Shells that are
-not part of Berkeley
-.UX ,
-as shells from Berkeley don't do error control. You can get a similar
-effect, however, by changing the last three lines to be:
-.DS
-       hasErrCtl=no \e
-       check="echo \e"+ %s\e"\en" \e
-       ignore="sh -c '%s || exit 0\en"
-.DE
-.LP
-This will cause PMake to execute the two commands
-.DS
-echo "+ \fIcmd\fP"
-sh -c '\fIcmd\fP || true'
-.DE
-for each command for which errors are to be ignored. (In case you are
-wondering, the thing for
-.CW ignore
-tells the shell to execute another shell without error checking on and
-always exit 0, since the
-.B ||
-causes the
-.CW "exit 0"
-to be executed only if the first command exited non-zero, and if the
-first command exited zero, the shell will also exit zero, since that's
-the last command it executed).
-.xH 2 Compatibility
-.Ix 0 ref compatibility
-.LP
-There are three (well, 3 \(12) levels of backwards-compatibility built
-into PMake.  Most makefiles will need none at all. Some may need a
-little bit of work to operate correctly when run in parallel. Each
-level encompasses the previous levels (e.g.
-.B \-B
-(one shell per command) implies
-.B \-V )
-The three levels are described in the following three sections.
-.xH 3 DEFCON 3 \*- Variable Expansion
-.Ix 0 ref compatibility
-.LP
-As noted before, PMake will not expand a variable unless it knows of a
-value for it. This can cause problems for makefiles that expect to
-leave variables undefined except in special circumstances (e.g. if
-more flags need to be passed to the C compiler or the output from a
-text processor should be sent to a different printer). If the
-variables are enclosed in curly braces
-.CW ${PRINTER} ''), (``
-the shell will let them pass. If they are enclosed in parentheses,
-however, the shell will declare a syntax error and the make will come
-to a grinding halt.
-.LP
-You have two choices: change the makefile to define the variables
-(their values can be overridden on the command line, since that's
-where they would have been set if you used Make, anyway) or always give the
-.B \-V
-flag (this can be done with the
-.CW .MAKEFLAGS
-target, if you want).
-.xH 3 DEFCON 2 \*- The Number of the Beast
-.Ix 0 ref compatibility
-.LP
-Then there are the makefiles that expect certain commands, such as
-changing to a different directory, to not affect other commands in a
-target's creation script. You can solve this is either by going
-back to executing one shell per command (which is what the
-.B \-B
-flag forces PMake to do), which slows the process down a good bit and
-requires you to use semicolons and escaped newlines for shell constructs, or
-by changing the makefile to execute the offending command(s) in a subshell
-(by placing the line inside parentheses), like so:
-.DS
-install :: .MAKE
-       (cd src; $(.PMAKE) install)
-       (cd lib; $(.PMAKE) install)
-       (cd man; $(.PMAKE) install)
-.DE
-.Ix 0 ref operator double-colon
-.Ix 0 ref variable global .PMAKE
-.Ix 0 ref .PMAKE
-.Ix 0 ref .MAKE
-.Ix 0 ref attribute .MAKE
-This will always execute the three makes (even if the
-.B \-n
-flag was given) because of the combination of the ``::'' operator and
-the
-.CW .MAKE
-attribute. Each command will change to the proper directory to perform
-the install, leaving the main shell in the directory in which it started.
-.xH 3 "DEFCON 1 \*- Imitation is the Not the Highest Form of Flattery"
-.Ix 0 ref compatibility
-.LP
-The final category of makefile is the one where every command requires
-input, the dependencies are incompletely specified, or you simply
-cannot create more than one target at a time, as mentioned earlier. In
-addition, you may not have the time or desire to upgrade the makefile
-to run smoothly with PMake. If you are the conservative sort, this is
-the compatibility mode for you. It is entered either by giving PMake
-the
-.B \-M
-flag (for Make), or by executing PMake as
-.CW make .'' ``
-In either case, PMake performs things exactly like Make (while still
-supporting most of the nice new features PMake provides). This
-includes:
-.IP \(bu 2
-No parallel execution.
-.IP \(bu 2
-Targets are made in the exact order specified by the makefile. The
-sources for each target are made in strict left-to-right order, etc.
-.IP \(bu 2
-A single Bourne shell is used to execute each command, thus the
-shell's
-.CW $$
-variable is useless, changing directories doesn't work across command
-lines, etc.
-.IP \(bu 2
-If no special characters exist in a command line, PMake will break the
-command into words itself and execute the command directly, without
-executing a shell first. The characters that cause PMake to execute a
-shell are:
-.CW # ,
-.CW = ,
-.CW | ,
-.CW ^ ,
-.CW ( ,
-.CW ) ,
-.CW { ,
-.CW } ,
-.CW ; ,
-.CW & ,
-.CW < ,
-.CW > ,
-.CW * ,
-.CW ? ,
-.CW [ ,
-.CW ] ,
-.CW : ,
-.CW $ ,
-.CW ` ,
-and
-.CW \e .
-You should notice that these are all the characters that are given
-special meaning by the shell (except
-.CW '
-and
-.CW " ,
-which PMake deals with all by its lonesome).
-.IP \(bu 2
-The use of the null suffix is turned off.
-.Ix 0 ref "null suffix"
-.Ix 0 ref suffix null
-.xH 2 The Way Things Work
-.LP
-When PMake reads the makefile, it parses sources and targets into
-nodes in a graph. The graph is directed only in the sense that PMake
-knows which way is up. Each node contains not only links to all its
-parents and children (the nodes that depend on it and those on which
-it depends, respectively), but also a count of the number of its
-children that have already been processed.
-.LP
-The most important thing to know about how PMake uses this graph is
-that the traversal is breadth-first and occurs in two passes.
-.LP
-After PMake has parsed the makefile, it begins with the nodes the user
-has told it to make (either on the command line, or via a 
-.CW .MAIN
-target, or by the target being the first in the file not labeled with
-the
-.CW .NOTMAIN
-attribute) placed in a queue. It continues to take the node off the
-front of the queue, mark it as something that needs to be made, pass
-the node to 
-.CW Suff_FindDeps
-(mentioned earlier) to find any implicit sources for the node, and
-place all the node's children that have yet to be marked at the end of
-the queue. If any of the children is a
-.CW .USE
-rule, its attributes are applied to the parent, then its commands are
-appended to the parent's list of commands and its children are linked
-to its parent. The parent's unmade children counter is then decremented
-(since the
-.CW .USE
-node has been processed). You will note that this allows a
-.CW .USE
-node to have children that are
-.CW .USE
-nodes and the rules will be applied in sequence.
-If the node has no children, it is placed at the end of
-another queue to be examined in the second pass. This process
-continues until the first queue is empty.
-.LP
-At this point, all the leaves of the graph are in the examination
-queue. PMake removes the node at the head of the queue and sees if it
-is out-of-date. If it is, it is passed to a function that will execute
-the commands for the node asynchronously. When the commands have
-completed, all the node's parents have their unmade children counter
-decremented and, if the counter is then 0, they are placed on the
-examination queue. Likewise, if the node is up-to-date. Only those
-parents that were marked on the downward pass are processed in this
-way. Thus PMake traverses the graph back up to the nodes the user
-instructed it to create. When the examination queue is empty and no
-shells are running to create a target, PMake is finished.
-.LP
-Once all targets have been processed, PMake executes the commands
-attached to the
-.CW .END
-target, either explicitly or through the use of an ellipsis in a shell
-script. If there were no errors during the entire process but there
-are still some targets unmade (PMake keeps a running count of how many
-targets are left to be made), there is a cycle in the graph. PMake does
-a depth-first traversal of the graph to find all the targets that
-weren't made and prints them out one by one.
-.xH 1 Answers to Exercises
-.IP (3.1)
-This is something of a trick question, for which I apologize. The
-trick comes from the UNIX definition of a suffix, which PMake doesn't
-necessarily share. You will have noticed that all the suffixes used in
-this tutorial (and in UNIX in general) begin with a period
-.CW .ms , (
-.CW .c ,
-etc.). Now, PMake's idea of a suffix is more like English's: it's the
-characters at the end of a word. With this in mind, one possible
-.Ix 0 def suffix
-solution to this problem goes as follows:
-.DS I
-\&.SUFFIXES       : ec.exe .exe ec.obj .obj .asm
-ec.objec.exe .obj.exe :
-        link -o $(.TARGET) $(.IMPSRC)
-\&.asmec.obj      :
-        asm -o $(.TARGET) -DDO_ERROR_CHECKING $(.IMPSRC)
-\&.asm.obj        :
-        asm -o $(.TARGET) $(.IMPSRC)
-.DE
-.IP (3.2)
-The trick to this one lies in the ``:='' variable-assignment operator
-and the ``:S'' variable-expansion modifier. 
-.Ix 0 ref variable assignment expanded
-.Ix 0 ref variable expansion modified
-.Ix 0 ref modifier substitute
-.Ix 0 ref :S
-.Ix 0 ref :=
-Basically what you want is to take the pointer variable, so to speak,
-and transform it into an invocation of the variable at which it
-points. You might try something like
-.DS I
-$(PTR:S/^/\e$(/:S/$/))
-.DE
-which places
-.CW $( '' ``
-at the front of the variable name and
-.CW ) '' ``
-at the end, thus transforming
-.CW VAR ,'' ``
-for example, into
-.CW $(VAR) ,'' ``
-which is just what we want. Unfortunately (as you know if you've tried
-it), since, as it says in the hint, PMake does no further substitution
-on the result of a modified expansion, that's \fIall\fP you get. The
-solution is to make use of ``:='' to place that string into yet
-another variable, then invoke the other variable directly:
-.DS I
-*PTR            := $(PTR:S/^/\e$(/:S/$/)/)
-.DE
-You can then use
-.CW $(*PTR) '' ``
-to your heart's content.
-.de Gp
-.XP
-\&\fB\\$1:\fP
-..
-.xH 1 Glossary of Jargon
-.Gp "attribute"
-A property given to a target that causes PMake to treat it differently.
-.Gp "command script"
-The lines immediately following a dependency line that specify
-commands to execute to create each of the targets on the dependency
-line. Each line in the command script must begin with a tab.
-.Gp "command-line variable"
-A variable defined in an argument when PMake is first executed.
-Overrides all assignments to the same variable name in the makefile.
-.Gp "conditional"
-A construct much like that used in C that allows a makefile to be
-configured on the fly based on the local environment, or on what is being
-made by that invocation of PMake.
-.Gp "creation script"
-Commands used to create a target. See ``command script.''
-.Gp "dependency"
-The relationship between a source and a target. This comes in three
-flavors, as indicated by the operator between the target and the
-source. `:' gives a straight time-wise dependency (if the target is
-older than the source, the target is out-of-date), while `!' provides
-simply an ordering and always considers the target out-of-date. `::'
-is much like `:', save it creates multiple instances of a target each
-of which depends on its own list of sources.
-.Gp "dynamic source"
-This refers to a source that has a local variable invocation in it. It
-allows a single dependency line to specify a different source for each
-target on the line.
-.Gp "global variable"
-Any variable defined in a makefile. Takes precedence over variables
-defined in the environment, but not over command-line or local variables.
-.Gp "input graph"
-What PMake constructs from a makefile. Consists of nodes made of the
-targets in the makefile, and the links between them (the
-dependencies). The links are directed (from source to target) and
-there may not be any cycles (loops) in the graph.
-.Gp "local variable"
-A variable defined by PMake visible only in a target's shell script.
-There are seven local variables, not all of which are defined for
-every target:
-.CW .TARGET ,
-.CW .ALLSRC ,
-.CW .OODATE ,
-.CW .PREFIX ,
-.CW .IMPSRC ,
-.CW .ARCHIVE ,
-and
-.CW .MEMBER .
-.CW .TARGET ,
-.CW .PREFIX ,
-.CW .ARCHIVE ,
-and 
-.CW .MEMBER
-may be used on dependency lines to create ``dynamic sources.''
-.Gp "makefile"
-A file that describes how a system is built. If you don't know what it
-is after reading this tutorial.\|.\|.\|.
-.Gp "modifier"
-A letter, following a colon, used to alter how a variable is expanded.
-It has no effect on the variable itself.
-.Gp "operator"
-What separates a source from a target (on a dependency line) and specifies
-the relationship between the two. There are three:
-.CW : ', `
-.CW :: ', `
-and
-.CW ! '. `
-.Gp "search path"
-A list of directories in which a file should be sought. PMake's view
-of the contents of directories in a search path does not change once
-the makefile has been read. A file is sought on a search path only if
-it is exclusively a source.
-.Gp "shell"
-A program to which commands are passed in order to create targets.
-.Gp "source"
-Anything to the right of an operator on a dependency line. Targets on
-the dependency line are usually created from the sources.
-.Gp "special target"
-A target that causes PMake to do special things when it's encountered.
-.Gp "suffix"
-The tail end of a file name. Usually begins with a period,
-.CW .c
-or
-.CW .ms ,
-e.g.
-.Gp "target"
-A word to the left of the operator on a dependency line. More
-generally, any file that PMake might create. A file may be (and often
-is) both a target and a source (what it is depends on how PMake is
-looking at it at the time \*- sort of like the wave/particle duality
-of light, you know).
-.Gp "transformation rule"
-A special construct in a makefile that specifies how to create a file
-of one type from a file of another, as indicated by their suffixes.
-.Gp "variable expansion"
-The process of substituting the value of a variable for a reference to
-it. Expansion may be altered by means of modifiers.
-.Gp "variable"
-A place in which to store text that may be retrieved later. Also used
-to define the local environment. Conditionals exist that test whether
-a variable is defined or not.
-.bp
-.\" Output table of contents last, with an entry for the index, making
-.\" sure to save and restore the last real page number for the index...
-.nr @n \n(PN+1
-.\" We are not generating an index
-.\" .XS \n(@n
-.\" Index
-.\" .XE
-.nr %% \n%
-.PX
-.nr % \n(%%
diff --git a/usr.bin/make/arch.c b/usr.bin/make/arch.c
deleted file mode 100644 (file)
index e795f08..0000000
+++ /dev/null
@@ -1,1226 +0,0 @@
-/*-
- * Copyright (c) 1988, 1989, 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- * Copyright (c) 1989 by Berkeley Softworks
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Adam de Boor.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)arch.c  8.2 (Berkeley) 1/2/94
- * $FreeBSD: src/usr.bin/make/arch.c,v 1.48 2005/02/10 14:39:05 harti Exp $
- * $DragonFly: src/usr.bin/make/arch.c,v 1.55 2005/09/24 07:37:01 okumoto Exp $
- */
-
-/*-
- * arch.c --
- *     Functions to manipulate libraries, archives and their members.
- *
- *     Once again, cacheing/hashing comes into play in the manipulation
- * of archives. The first time an archive is referenced, all of its members'
- * headers are read and hashed and the archive closed again. All hashed
- * archives are kept on a list which is searched each time an archive member
- * is referenced.
- *
- * The interface to this module is:
- *     Arch_ParseArchive       Given an archive specification, return a list
- *                             of GNode's, one for each member in the spec.
- *                             false is returned if the specification is
- *                             invalid for some reason.
- *
- *     Arch_Touch              Alter the modification time of the archive
- *                             member described by the given node to be
- *                             the current time.
- *
- *     Arch_TouchLib           Update the modification time of the library
- *                             described by the given node. This is special
- *                             because it also updates the modification time
- *                             of the library's table of contents.
- *
- *     Arch_MTime              Find the modification time of a member of
- *                             an archive *in the archive*. The time is also
- *                             placed in the member's GNode. Returns the
- *                             modification time.
- *
- *     Arch_MemTime            Find the modification time of a member of
- *                             an archive. Called when the member doesn't
- *                             already exist. Looks in the archive for the
- *                             modification time. Returns the modification
- *                             time.
- *
- *     Arch_FindLib            Search for a library along a path. The
- *                             library name in the GNode should be in
- *                             -l<name> format.
- *
- *     Arch_LibOODate          Special function to decide if a library node
- *                             is out-of-date.
- *
- *     Arch_Init               Initialize this module.
- */
-
-#include <sys/param.h>
-#include <sys/queue.h>
-#include <sys/types.h>
-#include <ar.h>
-#include <ctype.h>
-#include <errno.h>
-#include <inttypes.h>
-#include <regex.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <utime.h>
-
-#include "arch.h"
-#include "buf.h"
-#include "config.h"
-#include "dir.h"
-#include "globals.h"
-#include "GNode.h"
-#include "hash.h"
-#include "make.h"
-#include "parse.h"
-#include "targ.h"
-#include "util.h"
-#include "var.h"
-
-typedef struct Arch {
-       char            *name;          /* Name of archive */
-
-       /*
-        * All the members of the archive described
-        * by <name, struct ar_hdr *> key/value pairs
-        */
-       Hash_Table      members;
-
-       TAILQ_ENTRY(Arch) link;         /* link all cached archives */
-} Arch;
-
-/* Lst of archives we've already examined */
-static TAILQ_HEAD(, Arch) archives = TAILQ_HEAD_INITIALIZER(archives);
-
-
-/* size of the name field in the archive member header */
-#define        AR_NAMSIZ       sizeof(((struct ar_hdr *)0)->ar_name)
-
-/*
- * This structure is used while reading/writing an archive
- */
-struct arfile {
-       FILE            *fp;            /* archive file */
-       char            *fname;         /* name of the file */
-       struct ar_hdr   hdr;            /* current header */
-       char            sname[AR_NAMSIZ + 1]; /* short name */
-       char            *member;        /* (long) member name */
-       size_t          mlen;           /* size of the above */
-       char            *nametab;       /* name table */
-       size_t          nametablen;     /* size of the table */
-       int64_t         time;           /* from ar_date */
-       uint64_t        size;           /* from ar_size */
-       off_t           pos;            /* header pos of current entry */
-};
-
-/*
- * Name of the symbol table. The original BSD used "__.SYMDEF". Rumours go
- * that this name may have a slash appended sometimes. Actually FreeBSD
- * uses "/" which probably came from SVR4.
- */
-#define        SVR4_RANLIBMAG  "/"
-#define        BSD_RANLIBMAG   "__.SYMDEF"
-
-/*
- * Name of the filename table. The 4.4BSD ar format did not use this, but
- * puts long filenames directly between the member header and the object
- * file.
- */
-#define        SVR4_NAMEMAG    "//"
-#define        BSD_NAMEMAG     "ARFILENAMES/"
-
-/*
- * 44BSD long filename key. Use a local define here instead of relying
- * on ar.h because we want this to continue working even when the
- * definition is removed from ar.h.
- */
-#define        BSD_EXT1        "#1/"
-#define        BSD_EXT1LEN     3
-
-/* if this is true make archive errors fatal */
-bool arch_fatal = true;
-
-/**
- * ArchError
- *     An error happend while handling an archive. BSDmake traditionally
- *     ignored these errors. Now this is dependend on the global arch_fatal
- *     which, if true, makes these errors fatal and, if false, just emits an
- *     error message.
- */
-#define        ArchError(ARGS) do {                                    \
-       if (arch_fatal)                                         \
-               Fatal ARGS;                                     \
-       else                                                    \
-               Error ARGS;                                     \
-    } while (0)
-
-/*-
- *-----------------------------------------------------------------------
- * Arch_ParseArchive --
- *     Parse the archive specification in the given line and find/create
- *     the nodes for the specified archive members, placing their nodes
- *     on the given list, given the pointer to the start of the
- *     specification, a Lst on which to place the nodes, and a context
- *     in which to expand variables.
- *
- * Results:
- *     true if it was a valid specification. The linePtr is updated
- *     to point to the first non-space after the archive spec. The
- *     nodes for the members are placed on the given list.
- *
- * Side Effects:
- *     Some nodes may be created. The given list is extended.
- *
- *-----------------------------------------------------------------------
- */
-bool
-Arch_ParseArchive(char **linePtr, Lst *nodeLst, GNode *ctxt)
-{
-       char    *cp;            /* Pointer into line */
-       GNode   *gn;            /* New node */
-       char    *libName;       /* Library-part of specification */
-       char    *memName;       /* Member-part of specification */
-       char    *nameBuf;       /* temporary place for node name */
-       char    saveChar;       /* Ending delimiter of member-name */
-       bool    subLibName;     /* true if libName should have/had
-                                * variable substitution performed on it */
-
-       libName = *linePtr;
-
-       subLibName = false;
-
-       for (cp = libName; *cp != OPEN_PAREN && *cp != '\0'; cp++) {
-               if (*cp == '$') {
-                       /*
-                        * Variable spec, so call the Var module to parse the
-                        * puppy so we can safely advance beyond it...
-                        */
-                       size_t  length = 0;
-                       bool    freeIt;
-                       char    *result;
-
-                       result = Var_Parse(cp, ctxt, true, &length, &freeIt);
-                       if (result == var_Error) {
-                               return (false);
-                       }
-                       subLibName = true;
-
-                       if (freeIt) {
-                               free(result);
-                       }
-                       cp += length - 1;
-               }
-       }
-
-       *cp++ = '\0';
-       if (subLibName) {
-               libName = Buf_Peel(Var_Subst(libName, ctxt, true));
-       }
-
-       for (;;) {
-               /*
-                * First skip to the start of the member's name, mark that
-                * place and skip to the end of it (either white-space or
-                * a close paren).
-                */
-
-               /*
-                * true if need to substitute in memName
-                */
-               bool    doSubst = false;
-
-               while (*cp != '\0' && *cp != CLOSE_PAREN &&
-                   isspace((unsigned char)*cp)) {
-                       cp++;
-               }
-
-               memName = cp;
-               while (*cp != '\0' && *cp != CLOSE_PAREN &&
-                   !isspace((unsigned char)*cp)) {
-                       if (*cp == '$') {
-                               /*
-                                * Variable spec, so call the Var module to
-                                * parse the puppy so we can safely advance
-                                * beyond it...
-                                */
-                               size_t  length = 0;
-                               bool    freeIt;
-                               char    *result;
-
-                               result = Var_Parse(cp, ctxt, true,
-                                   &length, &freeIt);
-                               if (result == var_Error) {
-                                       return (false);
-                               }
-                               doSubst = true;
-
-                               if (freeIt) {
-                                       free(result);
-                               }
-                               cp += length;
-                       } else {
-                               cp++;
-                       }
-               }
-
-               /*
-                * If the specification ends without a closing parenthesis,
-                * chances are there's something wrong (like a missing
-                * backslash), so it's better to return failure than allow
-                * such things to happen
-                */
-               if (*cp == '\0') {
-                       printf("No closing parenthesis in archive "
-                           "specification\n");
-                       return (false);
-               }
-
-               /*
-                * If we didn't move anywhere, we must be done
-                */
-               if (cp == memName) {
-                       break;
-               }
-
-               saveChar = *cp;
-               *cp = '\0';
-
-               /*
-                * XXX: This should be taken care of intelligently by
-                * SuffExpandChildren, both for the archive and the member
-                * portions.
-                */
-               /*
-                * If member contains variables, try and substitute for them.
-                * This will slow down archive specs with dynamic sources, of
-                * course, since we'll be (non-)substituting them three times,
-                * but them's the breaks -- we need to do this since
-                * SuffExpandChildren calls us, otherwise we could assume the
-                * thing would be taken care of later.
-                */
-               if (doSubst) {
-                       char    *buf;
-                       char    *sacrifice;
-                       char    *oldMemName = memName;
-                       size_t  sz;
-                       Buffer  *buf1;
-
-                       /*
-                        * Now form an archive spec and recurse to deal with
-                        * nested variables and multi-word variable values....
-                        * The results are just placed at the end of the
-                        * nodeLst we're returning.
-                        */
-                       buf1 = Var_Subst(memName, ctxt, true);
-                       memName = Buf_Data(buf1);
-
-                       sz = strlen(memName) + strlen(libName) + 3;
-                       buf = emalloc(sz);
-
-                       snprintf(buf, sz, "%s(%s)", libName, memName);
-
-                       sacrifice = buf;
-
-                       if (strchr(memName, '$') &&
-                           strcmp(memName, oldMemName) == 0) {
-                               /*
-                                * Must contain dynamic sources, so we can't
-                                * deal with it now.
-                                * Just create an ARCHV node for the thing and
-                                * let SuffExpandChildren handle it...
-                                */
-                               gn = Targ_FindNode(buf, TARG_CREATE);
-
-                               if (gn == NULL) {
-                                       free(buf);
-                                       Buf_Destroy(buf1, false);
-                                       return (false);
-                               }
-                               gn->type |= OP_ARCHV;
-                               Lst_AtEnd(nodeLst, (void *)gn);
-                       } else if (!Arch_ParseArchive(&sacrifice, nodeLst,
-                           ctxt)) {
-                               /*
-                                * Error in nested call -- free buffer and
-                                * return false ourselves.
-                                */
-                               free(buf);
-                               Buf_Destroy(buf1, false);
-                               return (false);
-                       }
-
-                       /* Free buffer and continue with our work. */
-                       free(buf);
-                       Buf_Destroy(buf1, false);
-
-               } else if (Dir_HasWildcards(memName)) {
-                       Lst     members = Lst_Initializer(members);
-                       char    *member;
-                       size_t  sz = MAXPATHLEN;
-                       size_t  nsz;
-
-                       nameBuf = emalloc(sz);
-
-                       Path_Expand(memName, &dirSearchPath, &members);
-                       while (!Lst_IsEmpty(&members)) {
-                               member = Lst_DeQueue(&members);
-                               nsz = strlen(libName) + strlen(member) + 3;
-                               if (nsz > sz) {
-                                       sz = nsz * 2;
-                                       nameBuf = erealloc(nameBuf, sz);
-                               }
-
-                               snprintf(nameBuf, sz, "%s(%s)",
-                                   libName, member);
-                               free(member);
-                               gn = Targ_FindNode(nameBuf, TARG_CREATE);
-                               if (gn == NULL) {
-                                       free(nameBuf);
-                                       /* XXXHB Lst_Destroy(&members) */
-                                       return (false);
-                               }
-                               /*
-                                * We've found the node, but have to make sure
-                                * the rest of the world knows it's an archive
-                                * member, without having to constantly check
-                                * for parentheses, so we type the thing with
-                                * the OP_ARCHV bit before we place it on the
-                                * end of the provided list.
-                                */
-                               gn->type |= OP_ARCHV;
-                               Lst_AtEnd(nodeLst, gn);
-                       }
-                       free(nameBuf);
-               } else {
-                       size_t  sz = strlen(libName) + strlen(memName) + 3;
-
-                       nameBuf = emalloc(sz);
-                       snprintf(nameBuf, sz, "%s(%s)", libName, memName);
-                       gn = Targ_FindNode(nameBuf, TARG_CREATE);
-                       free(nameBuf);
-                       if (gn == NULL) {
-                               return (false);
-                       }
-                       /*
-                        * We've found the node, but have to make sure the
-                        * rest of the world knows it's an archive member,
-                        * without having to constantly check for parentheses,
-                        * so we type the thing with the OP_ARCHV bit before
-                        * we place it on the end of the provided list.
-                        */
-                       gn->type |= OP_ARCHV;
-                       Lst_AtEnd(nodeLst, gn);
-               }
-               if (doSubst) {
-                       free(memName);
-               }
-
-               *cp = saveChar;
-       }
-
-       /*
-        * If substituted libName, free it now, since we need it no longer.
-        */
-       if (subLibName) {
-               free(libName);
-       }
-
-       /*
-        * We promised the pointer would be set up at the next non-space, so
-        * we must advance cp there before setting *linePtr... (note that on
-        * entrance to the loop, cp is guaranteed to point at a CLOSE_PAREN)
-        */
-       do {
-               cp++;
-       } while (*cp != '\0' && isspace((unsigned char)*cp));
-
-       *linePtr = cp;
-       return (true);
-}
-
-/*
- * Close an archive file an free all resources
- */
-static void
-ArchArchiveClose(struct arfile *ar)
-{
-
-       if (ar->nametab != NULL)
-               free(ar->nametab);
-       free(ar->member);
-       if (ar->fp != NULL) {
-               if (fclose(ar->fp) == EOF)
-                       ArchError(("%s: close error", ar->fname));
-       }
-       free(ar->fname);
-       free(ar);
-}
-
-/*
- * Open an archive file.
- */
-static struct arfile *
-ArchArchiveOpen(const char *archive, const char *mode)
-{
-       struct arfile *ar;
-       char    magic[SARMAG];
-
-       ar = emalloc(sizeof(*ar));
-       ar->fname = estrdup(archive);
-       ar->mlen = 100;
-       ar->member = emalloc(ar->mlen);
-       ar->nametab = NULL;
-       ar->nametablen = 0;
-
-       if ((ar->fp = fopen(ar->fname, mode)) == NULL) {
-               DEBUGM(ARCH, ("%s", ar->fname));
-               ArchArchiveClose(ar);
-               return (NULL);
-       }
-
-       /* read MAGIC */
-       if (fread(magic, SARMAG, 1, ar->fp) != 1 ||
-           strncmp(magic, ARMAG, SARMAG) != 0) {
-               ArchError(("%s: bad archive magic\n", ar->fname));
-               ArchArchiveClose(ar);
-               return (NULL);
-       }
-
-       ar->pos = 0;
-       return (ar);
-}
-
-/*
- * Read the next header from the archive. The return value will be +1 if
- * the header is read successfully, 0 on EOF and -1 if an error happend.
- * On a successful return sname contains the truncated member name and
- * member the full name. hdr contains the member header. For the symbol table
- * names of length 0 are returned. The entry for the file name table is never
- * returned.
- */
-static int
-ArchArchiveNext(struct arfile *ar)
-{
-       char    *end;
-       int     have_long_name;
-       u_long  offs;
-       char    *ptr;
-       size_t  ret;
-       char    buf[MAX(sizeof(ar->hdr.ar_size), sizeof(ar->hdr.ar_date)) + 1];
-
-  next:
-       /*
-        * Seek to the next header.
-        */
-       if (ar->pos == 0) {
-               ar->pos = SARMAG;
-       } else {
-               ar->pos += sizeof(ar->hdr) + ar->size;
-               if (ar->size % 2 == 1)
-                       ar->pos++;
-       }
-
-       if (fseeko(ar->fp, ar->pos, SEEK_SET) == -1) {
-               ArchError(("%s: cannot seek to %jd: %s", ar->fname,
-                   (intmax_t)ar->pos, strerror(errno)));
-               return (-1);
-       }
-
-       /*
-        * Read next member header
-        */
-       ret = fread(&ar->hdr, sizeof(ar->hdr), 1, ar->fp);
-       if (ret != 1) {
-               if (feof(ar->fp))
-                       return (0);
-               ArchError(("%s: error reading member header: %s", ar->fname,
-                   strerror(errno)));
-               return (-1);
-       }
-       if (strncmp(ar->hdr.ar_fmag, ARFMAG, sizeof(ar->hdr.ar_fmag)) != 0) {
-               ArchError(("%s: bad entry magic", ar->fname));
-               return (-1);
-       }
-
-       /*
-        * looks like a member - get name by stripping trailing spaces
-        * and NUL terminating.
-        */
-       strncpy(ar->sname, ar->hdr.ar_name, AR_NAMSIZ);
-       ar->sname[AR_NAMSIZ] = '\0';
-       for (ptr = ar->sname + AR_NAMSIZ; ptr > ar->sname; ptr--)
-               if (ptr[-1] != ' ')
-                       break;
-
-       *ptr = '\0';
-
-       /*
-        * Parse the size. All entries need to have a size. Be careful
-        * to not allow buffer overruns.
-        */
-       strncpy(buf, ar->hdr.ar_size, sizeof(ar->hdr.ar_size));
-       buf[sizeof(ar->hdr.ar_size)] = '\0';
-
-       errno = 0;
-       ar->size = strtoumax(buf, &end, 10);
-       if (errno != 0 || strspn(end, " ") != strlen(end)) {
-               ArchError(("%s: bad size format in archive '%s'",
-                   ar->fname, buf));
-               return (-1);
-       }
-
-       /*
-        * Look for the extended name table. Do this before parsing
-        * the date because this table doesn't need a date.
-        */
-       if (strcmp(ar->sname, BSD_NAMEMAG) == 0 ||
-           strcmp(ar->sname, SVR4_NAMEMAG) == 0) {
-               /* filename table - read it in */
-               ar->nametablen = ar->size;
-               ar->nametab = emalloc(ar->nametablen);
-
-               ret = fread(ar->nametab, 1, ar->nametablen, ar->fp);
-               if (ret != ar->nametablen) {
-                       if (ferror(ar->fp)) {
-                               ArchError(("%s: cannot read nametab: %s",
-                                   ar->fname, strerror(errno)));
-                       } else {
-                               ArchError(("%s: cannot read nametab: "
-                                   "short read", ar->fname));
-                       }
-                       return (-1);
-               }
-
-               /*
-                * NUL terminate the entries. Entries are \n terminated
-                * and may have a trailing / or \.
-                */
-               ptr = ar->nametab;
-               while (ptr < ar->nametab + ar->nametablen) {
-                       if (*ptr == '\n') {
-                               if (ptr[-1] == '/' || ptr[-1] == '\\')
-                                       ptr[-1] = '\0';
-                               *ptr = '\0';
-                       }
-                       ptr++;
-               }
-
-               /* get next archive entry */
-               goto next;
-       }
-
-       /*
-        * Now parse the modification date. Be careful to not overrun
-        * buffers.
-        */
-       strncpy(buf, ar->hdr.ar_date, sizeof(ar->hdr.ar_date));
-       buf[sizeof(ar->hdr.ar_date)] = '\0';
-
-       errno = 0;
-       ar->time = (int64_t)strtoll(buf, &end, 10);
-       if (errno != 0 || strspn(end, " ") != strlen(end)) {
-               ArchError(("%s: bad date format in archive '%s'",
-                   ar->fname, buf));
-               return (-1);
-       }
-
-       /*
-        * Now check for the symbol table. This should really be the first
-        * entry, but we don't check this.
-        */
-       if (strcmp(ar->sname, BSD_RANLIBMAG) == 0 ||
-           strcmp(ar->sname, SVR4_RANLIBMAG) == 0) {
-               /* symbol table - return a zero length name */
-               ar->member[0] = '\0';
-               ar->sname[0] = '\0';
-               return (1);
-       }
-
-       have_long_name = 0;
-
-       /*
-        * Look whether this is a long name. There are several variants
-        * of long names:
-        *      "#1/12          "       - 12 length of following filename
-        *      "/17            "       - index into name table
-        *      " 17            "       - index into name table
-        * Note that in the last case we must also check that there is no
-        * slash in the name because of filenames with leading spaces:
-        *      " 777.o/           "    - filename 777.o
-        */
-       if (ar->sname[0] == '/' || (ar->sname[0] == ' ' &&
-           strchr(ar->sname, '/') == NULL)) {
-               /* SVR4 extended name */
-               errno = 0;
-               offs = strtoul(ar->sname + 1, &end, 10);
-               if (errno != 0 || *end != '\0' || offs >= ar->nametablen ||
-                   end == ar->sname + 1) {
-                       ArchError(("%s: bad extended name '%s'", ar->fname,
-                           ar->sname));
-                       return (-1);
-               }
-
-               /* fetch the name */
-               if (ar->mlen <= strlen(ar->nametab + offs)) {
-                       ar->mlen = strlen(ar->nametab + offs) + 1;
-                       ar->member = erealloc(ar->member, ar->mlen);
-               }
-               strcpy(ar->member, ar->nametab + offs);
-
-               have_long_name = 1;
-
-       } else if (strncmp(ar->sname, BSD_EXT1, BSD_EXT1LEN) == 0 &&
-           isdigit((unsigned char)ar->sname[BSD_EXT1LEN])) {
-               /* BSD4.4 extended name */
-               errno = 0;
-               offs = strtoul(ar->sname + BSD_EXT1LEN, &end, 10);
-               if (errno != 0 || *end != '\0' ||
-                   end == ar->sname + BSD_EXT1LEN) {
-                       ArchError(("%s: bad extended name '%s'", ar->fname,
-                           ar->sname));
-                       return (-1);
-               }
-
-               /* read it from the archive */
-               if (ar->mlen <= offs) {
-                       ar->mlen = offs + 1;
-                       ar->member = erealloc(ar->member, ar->mlen);
-               }
-               ret = fread(ar->member, 1, offs, ar->fp);
-               if (ret != offs) {
-                       if (ferror(ar->fp)) {
-                               ArchError(("%s: reading extended name: %s",
-                                   ar->fname, strerror(errno)));
-                       } else {
-                               ArchError(("%s: reading extended name: "
-                                   "short read", ar->fname));
-                       }
-                       return (-1);
-               }
-               ar->member[offs] = '\0';
-
-               have_long_name = 1;
-       }
-
-       /*
-        * Now remove the trailing slash that Svr4 puts at
-        * the end of the member name to support trailing spaces in names.
-        */
-       if (ptr > ar->sname && ptr[-1] == '/')
-               *--ptr = '\0';
-
-       if (!have_long_name) {
-               if (strlen(ar->sname) >= ar->mlen) {
-                       ar->mlen = strlen(ar->sname) + 1;
-                       ar->member = erealloc(ar->member, ar->mlen);
-               }
-               strcpy(ar->member, ar->sname);
-       }
-
-       return (1);
-}
-
-/*
- * Touch the current archive member by writing a new header with an
- * updated timestamp. The return value is 0 for success and -1 for errors.
- */
-static int
-ArchArchiveTouch(struct arfile *ar, int64_t ts)
-{
-
-       /* seek to our header */
-       if (fseeko(ar->fp, ar->pos, SEEK_SET) == -1) {
-               ArchError(("%s: cannot seek to %jd: %s", ar->fname,
-                   (intmax_t)ar->pos, strerror(errno)));
-               return (-1);
-       }
-
-       /*
-        * change timestamp, be sure to not NUL-terminated it, but
-        * to fill with spaces.
-        */
-       snprintf(ar->hdr.ar_date, sizeof(ar->hdr.ar_date), "%jd",
-           (intmax_t)ts);
-       memset(ar->hdr.ar_date + strlen(ar->hdr.ar_date),
-           ' ', sizeof(ar->hdr.ar_date) - strlen(ar->hdr.ar_date));
-
-       if (fwrite(&ar->hdr, sizeof(ar->hdr), 1, ar->fp) != 1) {
-               ArchError(("%s: cannot touch: %s", ar->fname, strerror(errno)));
-               return (-1);
-       }
-       return (0);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * ArchFindMember --
- *     Locate a member of an archive, given the path of the archive and
- *     the path of the desired member. If the archive is to be modified,
- *     the mode should be "r+", if not, it should be "r".  The archive
- *     file is returned positioned at the correct header.
- *
- * Results:
- *     A struct arfile *, opened for reading and, possibly writing,
- *     positioned at the member's header, or NULL if the member was
- *     nonexistent.
- *
- *-----------------------------------------------------------------------
- */
-static struct arfile *
-ArchFindMember(const char *archive, const char *member, const char *mode)
-{
-       struct arfile   *ar;
-       const char      *cp;    /* Useful character pointer */
-
-       if ((ar = ArchArchiveOpen(archive, mode)) == NULL)
-               return (NULL);
-
-       /*
-        * Because of space constraints and similar things, files are archived
-        * using their final path components, not the entire thing, so we need
-        * to point 'member' to the final component, if there is one, to make
-        * the comparisons easier...
-        */
-       if (member != NULL) {
-               cp = strrchr(member, '/');
-               if (cp != NULL) {
-                       member = cp + 1;
-               }
-       }
-
-       while (ArchArchiveNext(ar) > 0) {
-               /*
-                * When comparing there are actually three cases:
-                * (1) the name fits into the limit og af_name,
-                * (2) the name is longer and the archive supports long names,
-                * (3) the name is longer and the archive doesn't support long
-                * names.
-                * Because we don't know whether the archive supports long
-                * names or not we need to be carefull.
-                */
-               if (member == NULL) {
-                       /* special case - symbol table */
-                       if (ar->member[0] == '\0')
-                               return (ar);
-               } else if (strlen(member) <= AR_NAMSIZ) {
-                       /* case (1) */
-                       if (strcmp(ar->member, member) == 0)
-                               return (ar);
-               } else if (strcmp(ar->member, member) == 0) {
-                       /* case (3) */
-                       return (ar);
-               } else {
-                       /* case (2) */
-                       if (strlen(ar->member) == AR_NAMSIZ &&
-                           strncmp(member, ar->member, AR_NAMSIZ) == 0)
-                               return (ar);
-               }
-       }
-
-       /* not found */
-       ArchArchiveClose(ar);
-       return (NULL);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * ArchStatMember --
- *     Locate a member of an archive, given the path of the archive and
- *     the path of the desired member, and a boolean representing whether
- *     or not the archive should be hashed (if not already hashed).
- *
- * Results:
- *     A pointer to the current struct ar_hdr structure for the member. Note
- *     That no position is returned, so this is not useful for touching
- *     archive members. This is mostly because we have no assurances that
- *     The archive will remain constant after we read all the headers, so
- *     there's not much point in remembering the position...
- *
- * Side Effects:
- *
- *-----------------------------------------------------------------------
- */
-static int64_t
-ArchStatMember(const char *archive, const char *member, bool hash)
-{
-       struct arfile   *arf;
-       int64_t         ret;
-       int             t;
-       char            *cp;    /* Useful character pointer */
-       Arch            *ar;    /* Archive descriptor */
-       Hash_Entry      *he;    /* Entry containing member's description */
-       char            copy[AR_NAMSIZ + 1];
-
-       /*
-        * Because of space constraints and similar things, files are archived
-        * using their final path components, not the entire thing, so we need
-        * to point 'member' to the final component, if there is one, to make
-        * the comparisons easier...
-        */
-       if (member != NULL) {
-               cp = strrchr(member, '/');
-               if (cp != NULL)
-                       member = cp + 1;
-       }
-
-       TAILQ_FOREACH(ar, &archives, link) {
-               if (strcmp(archive, ar->name) == 0)
-                       break;
-       }
-       if (ar == NULL) {
-               /* archive not found */
-               if (!hash) {
-                       /*
-                        * Caller doesn't want the thing hashed, just use
-                        * ArchFindMember to read the header for the member
-                        * out and close down the stream again.
-                        */
-                       arf = ArchFindMember(archive, member, "r");
-                       if (arf == NULL) {
-                               return (INT64_MIN);
-                       }
-                       ret = arf->time;
-                       ArchArchiveClose(arf);
-                       return (ret);
-               }
-
-               /*
-                * We don't have this archive on the list yet, so we want to
-                * find out everything that's in it and cache it so we can get
-                * at it quickly.
-                */
-               arf = ArchArchiveOpen(archive, "r");
-               if (arf == NULL) {
-                       return (INT64_MIN);
-               }
-
-               /* create archive data structure */
-               ar = emalloc(sizeof(*ar));
-               ar->name = estrdup(archive);
-               Hash_InitTable(&ar->members, -1);
-
-               while ((t = ArchArchiveNext(arf)) > 0) {
-                       he = Hash_CreateEntry(&ar->members, arf->member, NULL);
-                       Hash_SetValue(he, emalloc(sizeof(int64_t)));
-                       *(int64_t *)Hash_GetValue(he) = arf->time;
-               }
-
-               ArchArchiveClose(arf);
-
-               if (t < 0) {
-                       /* error happend - throw away everything */
-                       Hash_DeleteTable(&ar->members);
-                       free(ar->name);
-                       free(ar);
-                       return (INT64_MIN);
-               }
-
-               TAILQ_INSERT_TAIL(&archives, ar, link);
-       }
-
-       /*
-        * Now that the archive has been read and cached, we can look into
-        * the hash table to find the desired member's header.
-        */
-       he = Hash_FindEntry(&ar->members, member);
-       if (he != NULL)
-               return (*(int64_t *)Hash_GetValue(he));
-
-       if (member != NULL && strlen(member) > AR_NAMSIZ) {
-               /* Try truncated name */
-               strncpy(copy, member, AR_NAMSIZ);
-               copy[AR_NAMSIZ] = '\0';
-
-               if ((he = Hash_FindEntry(&ar->members, copy)) != NULL)
-                       return (*(int64_t *)Hash_GetValue(he));
-       }
-
-       return (INT64_MIN);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * Arch_Touch --
- *     Touch a member of an archive.
- *
- * Results:
- *     The 'time' field of the member's header is updated.
- *
- * Side Effects:
- *     The modification time of the entire archive is also changed.
- *     For a library, this could necessitate the re-ranlib'ing of the
- *     whole thing.
- *
- *-----------------------------------------------------------------------
- */
-void
-Arch_Touch(GNode *gn)
-{
-       struct arfile   *ar;
-
-       ar = ArchFindMember(
-           Var_Value(ARCHIVE, gn), Var_Value(TARGET, gn), "r+");
-
-       if (ar != NULL) {
-               ArchArchiveTouch(ar, (int64_t)now);
-               ArchArchiveClose(ar);
-       }
-}
-
-/*-
- *-----------------------------------------------------------------------
- * Arch_TouchLib --
- *     Given a node which represents a library, touch the thing, making
- *     sure that the table of contents also is touched.
- *
- * Results:
- *     None.
- *
- * Side Effects:
- *     Both the modification time of the library and of the RANLIBMAG
- *     member are set to 'now'.
- *
- *-----------------------------------------------------------------------
- */
-void
-Arch_TouchLib(GNode *gn)
-{
-       struct arfile   *ar;    /* Open archive */
-       struct utimbuf  times;  /* Times for utime() call */
-
-       ar = ArchFindMember(gn->path, NULL, "r+");
-       if (ar != NULL) {
-               ArchArchiveTouch(ar, (int64_t)now);
-               ArchArchiveClose(ar);
-
-               times.actime = times.modtime = now;
-               utime(gn->path, &times);
-       }
-}
-
-/*-
- *-----------------------------------------------------------------------
- * Arch_MTime --
- *     Return the modification time of a member of an archive, given its
- *     name.
- *
- * Results:
- *     The modification time(seconds).
- *     XXXHB this should be a long.
- *
- * Side Effects:
- *     The mtime field of the given node is filled in with the value
- *     returned by the function.
- *
- *-----------------------------------------------------------------------
- */
-int
-Arch_MTime(GNode *gn)
-{
-       int64_t mtime;
-
-       mtime = ArchStatMember(
-           Var_Value(ARCHIVE, gn), Var_Value(TARGET, gn), true);
-
-       if (mtime == INT_MIN) {
-               mtime = 0;
-       }
-       gn->mtime = (int)mtime;                 /* XXX */
-       return (gn->mtime);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * Arch_MemMTime --
- *     Given a non-existent archive member's node, get its modification
- *     time from its archived form, if it exists.
- *
- * Results:
- *     The modification time.
- *
- * Side Effects:
- *     The mtime field is filled in.
- *
- *-----------------------------------------------------------------------
- */
-int
-Arch_MemMTime(GNode *gn)
-{
-       LstNode *ln;
-       GNode   *pgn;
-       char    *nameStart;
-       char    *nameEnd;
-
-       for (ln = Lst_First(&gn->parents); ln != NULL; ln = Lst_Succ(ln)) {
-               pgn = Lst_Datum(ln);
-
-               if (pgn->type & OP_ARCHV) {
-                       /*
-                        * If the parent is an archive specification and is
-                        * being made and its member's name matches the name of
-                        * the node we were given, record the modification time
-                        * of the parent in the child. We keep searching its
-                        * parents in case some other parent requires this
-                        * child to exist...
-                        */
-                       nameStart = strchr(pgn->name, OPEN_PAREN) + 1;
-                       nameEnd = strchr(nameStart, CLOSE_PAREN);
-
-                       if (pgn->make && strncmp(nameStart, gn->name,
-                           nameEnd - nameStart) == 0) {
-                               gn->mtime = Arch_MTime(pgn);
-                       }
-               } else if (pgn->make) {
-                       /*
-                        * Something which isn't a library depends on the
-                        * existence of this target, so it needs to exist.
-                        */
-                       gn->mtime = 0;
-                       break;
-               }
-       }
-       return (gn->mtime);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * Arch_FindLib --
- *     Search for a named library along the given search path.
- *
- * Results:
- *     None.
- *
- * Side Effects:
- *     The node's 'path' field is set to the found path (including the
- *     actual file name, not -l...). If the system can handle the -L
- *     flag when linking (or we cannot find the library), we assume that
- *     the user has placed the .LIBRARIES variable in the final linking
- *     command (or the linker will know where to find it) and set the
- *     TARGET variable for this node to be the node's name. Otherwise,
- *     we set the TARGET variable to be the full path of the library,
- *     as returned by Dir_FindFile.
- *
- *-----------------------------------------------------------------------
- */
-void
-Arch_FindLib(GNode *gn, struct Path *path)
-{
-       char    *libName;       /* file name for archive */
-       size_t  sz;
-
-       sz = strlen(gn->name) + 4;
-       libName = emalloc(sz);
-       snprintf(libName, sz, "lib%s.a", &gn->name[2]);
-
-       gn->path = Path_FindFile(libName, path);
-
-       free(libName);
-
-#ifdef LIBRARIES
-       Var_Set(TARGET, gn->name, gn);
-#else
-       Var_Set(TARGET, gn->path == NULL ? gn->name : gn->path, gn);
-#endif /* LIBRARIES */
-}
-
-/*-
- *-----------------------------------------------------------------------
- * Arch_LibOODate --
- *     Decide if a node with the OP_LIB attribute is out-of-date. Called
- *     from Make_OODate to make its life easier, with the library's
- *     graph node.
- *
- *     There are several ways for a library to be out-of-date that are
- *     not available to ordinary files. In addition, there are ways
- *     that are open to regular files that are not available to
- *     libraries. A library that is only used as a source is never
- *     considered out-of-date by itself. This does not preclude the
- *     library's modification time from making its parent be out-of-date.
- *     A library will be considered out-of-date for any of these reasons,
- *     given that it is a target on a dependency line somewhere:
- *         Its modification time is less than that of one of its
- *               sources (gn->mtime < gn->cmtime).
- *         Its modification time is greater than the time at which the
- *               make began (i.e. it's been modified in the course
- *               of the make, probably by archiving).
- *         The modification time of one of its sources is greater than
- *               the one of its RANLIBMAG member (i.e. its table of contents
- *               is out-of-date). We don't compare of the archive time
- *               vs. TOC time because they can be too close. In my
- *               opinion we should not bother with the TOC at all since
- *               this is used by 'ar' rules that affect the data contents
- *               of the archive, not by ranlib rules, which affect the
- *               TOC.
- *
- * Results:
- *     true if the library is out-of-date. false otherwise.
- *
- * Side Effects:
- *     The library will be hashed if it hasn't been already.
- *
- *-----------------------------------------------------------------------
- */
-bool
-Arch_LibOODate(GNode *gn)
-{
-       int64_t mtime;  /* The table-of-contents's mod time */
-
-       if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->children)) {
-               return (false);
-       }
-       if (gn->mtime > now || gn->mtime < gn->cmtime) {
-               return (true);
-       }
-
-       mtime = ArchStatMember(gn->path, NULL, false);
-       if (mtime == INT64_MIN) {
-               /*
-                * Not found. A library w/o a table of contents is out-of-date
-                */
-               if (DEBUG(ARCH) || DEBUG(MAKE)) {
-                       Debug("No TOC...");
-               }
-               return (true);
-       }
-
-       /* XXX choose one. */
-       if (DEBUG(ARCH) || DEBUG(MAKE)) {
-               Debug("TOC modified %s...", Targ_FmtTime(mtime));
-       }
-       return (gn->cmtime > mtime);
-}
diff --git a/usr.bin/make/arch.h b/usr.bin/make/arch.h
deleted file mode 100644 (file)
index 3e27711..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*-
- * Copyright (c) 1988, 1989, 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- * Copyright (c) 1989 by Berkeley Softworks
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Adam de Boor.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $DragonFly: src/usr.bin/make/arch.h,v 1.8 2005/08/03 19:48:44 okumoto Exp $
- */
-
-#ifndef arch_h_488adf7a
-#define        arch_h_488adf7a
-
-#include <stdbool.h>
-
-struct GNode;
-struct Lst;
-struct Path;
-
-/* archive errors are fatal */
-extern bool arch_fatal;
-
-bool Arch_ParseArchive(char **, struct Lst *, struct GNode *);
-void Arch_Touch(struct GNode *);
-void Arch_TouchLib(struct GNode *);
-int Arch_MTime(struct GNode *);
-int Arch_MemMTime(struct GNode *);
-void Arch_FindLib(struct GNode *, struct Path *);
-bool Arch_LibOODate(struct GNode *);
-
-#endif /* arch_h_488adf7a */
diff --git a/usr.bin/make/buf.c b/usr.bin/make/buf.c
deleted file mode 100644 (file)
index 9b30f93..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/*-
- * Copyright (c) 2005 Max Okumoto
- * Copyright (c) 1988, 1989, 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- * Copyright (c) 1988, 1989 by Adam de Boor
- * Copyright (c) 1989 by Berkeley Softworks
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Adam de Boor.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)buf.c   8.1 (Berkeley) 6/6/93
- * $FreeBSD: src/usr.bin/make/buf.c,v 1.32 2005/02/07 11:27:47 harti Exp $
- * $DragonFly: src/usr.bin/make/buf.c,v 1.43 2005/09/24 07:37:38 okumoto Exp $
- */
-
-/*
- * buf.c
- *     Functions for automatically-expanded buffers.
- */
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "buf.h"
-#include "util.h"
-
-/**
- * Returns the number of bytes in the buffer.  Doesn't include the
- * null-terminating byte.
- *
- * @return The number of bytes in Buffer object.
- */
-inline size_t
-Buf_Size(const Buffer *buf)
-{
-       return (buf->end - buf->buf);
-}
-
-/**
- * Returns a reference to the data contained in the buffer.
- *
- * @note Adding data to the Buffer object may invalidate the reference.
- */
-inline char *
-Buf_Data(const Buffer *bp)
-{
-       return (bp->buf);
-}
-
-/**
- * Expand the buffer to hold the number of additional bytes, plus
- * space to store a terminating NULL byte.
- */
-static inline void
-BufExpand(Buffer *bp, size_t nb)
-{
-       size_t  len = Buf_Size(bp);
-       if (bp->size < len + nb + 1) {
-               int size = bp->size + MAX(nb + 1, BUF_ADD_INC);
-
-               bp->buf         = erealloc(bp->buf, size);
-               bp->size        = size;
-               bp->end         = bp->buf + len;
-       }
-}
-
-/**
- * Add a single byte to the buffer.
- */
-inline void
-Buf_AddByte(Buffer *bp, char byte)
-{
-       BufExpand(bp, 1);
-
-       *bp->end = byte;
-       bp->end++;
-       *bp->end = '\0';
-}
-
-/**
- * Add bytes to the buffer.
- */
-void
-Buf_AddBytes(Buffer *bp, size_t len, const char bytes[])
-{
-       BufExpand(bp, len);
-
-       memcpy(bp->end, bytes, len);
-       bp->end += len;
-       *bp->end = '\0';
-}
-
-/**
- * Get the contents of a buffer and destroy the buffer. If the buffer
- * is NULL, return NULL.
- *
- * Returns:
- *     the pointer to the data.
- */
-char *
-Buf_Peel(Buffer *bp)
-{
-       char *ret;
-
-       if (bp == NULL)
-               return (NULL);
-       ret = bp->buf;
-       free(bp);
-       return (ret);
-}
-
-/**
- * Initialize a buffer. If no initial size is given, a reasonable
- * default is used.
- *
- * @return A buffer object to be given to other functions in this library.
- *
- * Side Effects:
- *     Space is allocated for the Buffer object and a internal buffer.
- */
-Buffer *
-Buf_Init(size_t size)
-{
-       Buffer *bp;     /* New Buffer */
-
-       if (size <= 0)
-               size = BUF_DEF_SIZE;
-
-       bp = emalloc(sizeof(*bp));
-       bp->size        = size;
-       bp->buf         = emalloc(size);
-       bp->end         = bp->buf;
-       *bp->end        = '\0';
-
-       return (bp);
-}
-
-/**
- * Destroy a buffer, and optionally free its data, too.
- *
- * Side Effects:
- *     Space for the Buffer object and possibly the internal buffer
- *     is de-allocated.
- */
-void
-Buf_Destroy(Buffer *buf, bool freeData)
-{
-       if (freeData)
-               free(buf->buf);
-       free(buf);
-}
-
-/**
- * Replace the last byte in a buffer.  If the buffer was empty
- * intially, then a new byte will be added.
- */
-void
-Buf_ReplaceLastByte(Buffer *bp, char byte)
-{
-       if (bp->end == bp->buf) {
-               Buf_AddByte(bp, byte);
-       } else {
-               *(bp->end - 1) = byte;
-       }
-}
-
-/**
- * Append characters in str to Buffer object
- */
-void
-Buf_Append(Buffer *bp, const char str[])
-{
-       Buf_AddBytes(bp, strlen(str), str);
-}
-
-/**
- * Append characters in buf to Buffer object
- */
-void
-Buf_AppendBuf(Buffer *bp, const Buffer *buf)
-{
-       Buf_AddBytes(bp, Buf_Size(buf), buf->buf);
-}
-
-/**
- * Append characters between str and end to Buffer object.
- */
-void
-Buf_AppendRange(Buffer *bp, const char str[], const char *end)
-{
-       Buf_AddBytes(bp, end - str, str);
-}
-
-/**
- * Convert newlines in buffer to spaces.  The trailing newline is
- * removed.
- */
-void
-Buf_StripNewlines(Buffer *bp)
-{
-       char *ptr = bp->end;
-
-       /*
-        * If there is anything in the buffer, remove the last
-        * newline character.
-        */
-       if (ptr != bp->buf) {
-               if (*(ptr - 1) == '\n') {
-                       /* shorten buffer */
-                       *(ptr - 1) = '\0';
-                       --bp->end;
-               }
-               --ptr;
-       }
-
-       /* Convert newline characters to a space characters.  */
-       while (ptr != bp->buf) {
-               if (*ptr == '\n') {
-                       *ptr = ' ';
-               }
-               --ptr;
-       }
-}
-
-/**
- * Clear the contents of the buffer.
- */
-void
-Buf_Clear(Buffer *bp)
-{
-       bp->end = bp->buf;
-       *bp->end = '\0';
-}
-
diff --git a/usr.bin/make/buf.h b/usr.bin/make/buf.h
deleted file mode 100644 (file)
index cb2ba96..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*-
- * Copyright (c) 1988, 1989, 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- * Copyright (c) 1988, 1989 by Adam de Boor
- * Copyright (c) 1989 by Berkeley Softworks
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Adam de Boor.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     from: @(#)buf.h 8.1 (Berkeley) 6/6/93
- * $FreeBSD: src/usr.bin/make/buf.h,v 1.24 2005/02/07 11:27:47 harti Exp $
- * $DragonFly: src/usr.bin/make/buf.h,v 1.36 2005/09/24 07:37:38 okumoto Exp $
- */
-
-#ifndef buf_h_a61a6812
-#define        buf_h_a61a6812
-
-/*-
- * buf.h --
- *     Header for users of the buf library.
- */
-
-#include <sys/types.h>
-#include <stdbool.h>
-
-/*
- * There are several places where expandable buffers are used (parse.c and
- * var.c). This constant is merely the starting point for those buffers. If
- * lines tend to be much shorter than this, it would be best to reduce BSIZE.
- * If longer, it should be increased. Reducing it will cause more copying to
- * be done for longer lines, but will save space for shorter ones. In any
- * case, it ought to be a power of two simply because most storage allocation
- * schemes allocate in powers of two.
- */
-#define        MAKE_BSIZE      256     /* starting size for expandable buffers */
-
-#define        BUF_DEF_SIZE    256     /* Default buffer size */
-#define        BUF_ADD_INC     256     /* Expansion increment when Adding */
-
-typedef struct Buffer {
-       size_t  size;   /* Current size of the buffer */
-       char    *buf;   /* The buffer itself */
-       char    *end;   /* Place to write to */
-} Buffer;
-
-void Buf_AddByte(Buffer *, char);
-void Buf_AddBytes(Buffer *, size_t, const char []);
-void Buf_Append(Buffer *, const char []);
-void Buf_AppendBuf(Buffer *, const Buffer *);
-void Buf_AppendRange(Buffer *, const char [], const char []);
-void Buf_Clear(Buffer *);
-char *Buf_Data(const Buffer *);
-void Buf_Destroy(Buffer *, bool);
-Buffer *Buf_Init(size_t);
-char *Buf_Peel(Buffer *);
-void Buf_ReplaceLastByte(Buffer *, char);
-size_t Buf_Size(const Buffer *);
-void Buf_StripNewlines(Buffer *);
-
-#endif /* buf_h_a61a6812 */
diff --git a/usr.bin/make/cond.c b/usr.bin/make/cond.c
deleted file mode 100644 (file)
index 6d6722b..0000000
+++ /dev/null
@@ -1,1227 +0,0 @@
-/*-
- * Copyright (c) 1988, 1989, 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- * Copyright (c) 1988, 1989 by Adam de Boor
- * Copyright (c) 1989 by Berkeley Softworks
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Adam de Boor.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)cond.c  8.2 (Berkeley) 1/2/94
- * $FreeBSD: src/usr.bin/make/cond.c,v 1.39 2005/02/07 07:49:16 harti Exp $
- * $DragonFly: src/usr.bin/make/cond.c,v 1.51 2005/09/24 07:38:03 okumoto Exp $
- */
-
-/*
- * Functions to handle conditionals in a makefile.
- *
- * Interface:
- *     Cond_Eval       Evaluate the conditional in the passed line.
- */
-
-#include <ctype.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "buf.h"
-#include "cond.h"
-#include "dir.h"
-#include "globals.h"
-#include "GNode.h"
-#include "make.h"
-#include "parse.h"
-#include "str.h"
-#include "targ.h"
-#include "util.h"
-#include "var.h"
-
-/*
- * The parsing of conditional expressions is based on this grammar:
- *     E -> F || E
- *     E -> F
- *     F -> T && F
- *     F -> T
- *     T -> defined(variable)
- *     T -> make(target)
- *     T -> exists(file)
- *     T -> empty(varspec)
- *     T -> target(name)
- *     T -> symbol
- *     T -> $(varspec) op value
- *     T -> $(varspec) == "string"
- *     T -> $(varspec) != "string"
- *     T -> ( E )
- *     T -> ! T
- *     op -> == | != | > | < | >= | <=
- *
- * 'symbol' is some other symbol to which the default function (condDefProc)
- * is applied.
- *
- * Tokens are scanned from the 'condExpr' string. The scanner (CondToken)
- * will return And for '&' and '&&', Or for '|' and '||', Not for '!',
- * LParen for '(', RParen for ')' and will evaluate the other terminal
- * symbols, using either the default function or the function given in the
- * terminal, and return the result as either True or False.
- *
- * All Non-Terminal functions (CondE, CondF and CondT) return Err on error.
- */
-typedef enum {
-       And,
-       Or,
-       Not,
-       True,
-       False,
-       LParen,
-       RParen,
-       EndOfFile,
-       None,
-       Err
-} Token;
-
-typedef bool CondProc(Parser *, int, char *);
-
-/*-
- * Structures to handle elegantly the different forms of #if's. The
- * last two fields are stored in condInvert and condDefProc, respectively.
- */
-static void CondPushBack(Token);
-static int CondGetArg(char **, char **, const char *, bool);
-static CondProc        CondDoDefined;
-static CondProc        CondDoMake;
-static CondProc        CondDoExists;
-static CondProc        CondDoTarget;
-static char *CondCvtArg(char *, double *);
-static Token CondToken(Parser *, bool);
-static Token CondT(Parser *, bool);
-static Token CondF(Parser *, bool);
-static Token CondE(Parser *, bool);
-
-static const struct If {
-       bool    doNot;          /* true if default function should be negated */
-       CondProc *defProc;      /* Default function to apply */
-       bool    isElse;         /* actually el<XXX> */
-} ifs[] = {
-       [COND_IF] =             { false,        CondDoDefined,  false },
-       [COND_IFDEF] =          { false,        CondDoDefined,  false },
-       [COND_IFNDEF] =         { true,         CondDoDefined,  false },
-       [COND_IFMAKE] =         { false,        CondDoMake,     false },
-       [COND_IFNMAKE] =        { true,         CondDoMake,     false },
-       [COND_ELIF] =           { false,        CondDoDefined,  true },
-       [COND_ELIFDEF] =        { false,        CondDoDefined,  true },
-       [COND_ELIFNDEF] =       { true,         CondDoDefined,  true },
-       [COND_ELIFMAKE] =       { false,        CondDoMake,     true },
-       [COND_ELIFNMAKE] =      { true,         CondDoMake,     true },
-};
-
-static bool    condInvert;     /* Invert the default function */
-static CondProc        *condDefProc;   /* default function to apply */
-static char    *condExpr;      /* The expression to parse */
-static Token   condPushBack = None; /* Single push-back token in parsing */
-
-#define MAXIF  30      /* greatest depth of #if'ing */
-
-static bool    condStack[MAXIF];       /* Stack of conditionals's values */
-static int     condLineno[MAXIF];      /* Line numbers of the opening .if */
-static int     condTop = MAXIF;        /* Top-most conditional */
-static int     skipIfLevel = 0;        /* Depth of skipped conditionals */
-static int     skipIfLineno[MAXIF];    /* Line numbers of skipped .ifs */
-bool           skipLine = false;       /* Whether the parse module is skipping
-                                        * lines */
-
-/**
- * CondPushBack
- *     Push back the most recent token read. We only need one level of
- *     this, so the thing is just stored in 'condPushback'.
- *
- * Side Effects:
- *     condPushback is overwritten.
- */
-static void
-CondPushBack(Token t)
-{
-
-       condPushBack = t;
-}
-
-/**
- * CondGetArg
- *     Find the argument of a built-in function.  parens is set to true
- *     if the arguments are bounded by parens.
- *
- * Results:
- *     The length of the argument and the address of the argument.
- *
- * Side Effects:
- *     The pointer is set to point to the closing parenthesis of the
- *     function call.
- */
-static int
-CondGetArg(char **linePtr, char **argPtr, const char *func, bool parens)
-{
-       char    *cp;
-       size_t  argLen;
-       Buffer  *buf;
-
-       cp = *linePtr;
-       if (parens) {
-               while (*cp != OPEN_PAREN && *cp != '\0') {
-                       cp++;
-               }
-               if (*cp == OPEN_PAREN) {
-                       cp++;
-               }
-       }
-
-       if (*cp == '\0') {
-               /*
-                * No arguments whatsoever. Because 'make' and 'defined'
-                * aren't really "reserved words", we don't print a message.
-                * I think this is better than hitting the user with a warning
-                * message every time s/he uses the word 'make' or 'defined'
-                * at the beginning of a symbol...
-                */
-               *argPtr = cp;
-               return (0);
-       }
-
-       while (*cp == ' ' || *cp == '\t') {
-               cp++;
-       }
-
-       /*
-        * Create a buffer for the argument and start it out at 16 characters
-        * long. Why 16? Why not?
-        */
-       buf = Buf_Init(16);
-
-       while ((strchr(" \t)&|", *cp) == NULL) && (*cp != '\0')) {
-               if (*cp == '$') {
-                       /*
-                        * Parse the variable spec and install it as part of
-                        * the argument if it's valid. We tell Var_Parse to
-                        * complain on an undefined variable, so we don't do
-                        * it too. Nor do we return an error, though perhaps
-                        * we should...
-                        */
-                       char    *cp2;
-                       size_t  len = 0;
-                       bool    doFree;
-
-                       cp2 = Var_Parse(cp, VAR_CMD, true, &len, &doFree);
-
-                       Buf_Append(buf, cp2);
-                       if (doFree) {
-                               free(cp2);
-                       }
-                       cp += len;
-               } else {
-                       Buf_AddByte(buf, *cp);
-                       cp++;
-               }
-       }
-
-       while (*cp == ' ' || *cp == '\t') {
-               cp++;
-       }
-
-       Buf_AddByte(buf, '\0');
-       *argPtr = Buf_Data(buf);
-       argLen = Buf_Size(buf);
-       Buf_Destroy(buf, false);
-
-       if (parens) {
-               if (*cp == CLOSE_PAREN) {
-                       /*
-                        * Advance pointer past close parenthesis.
-                        */
-                       cp++;
-                       *linePtr = cp;
-                       return (argLen);
-               } else {
-                       Parse_Error(PARSE_WARNING,
-                           "Missing closing parenthesis for %s()", func);
-                       return (0);
-                       /* XXX memory leak of argPtr? */
-               }
-       } else {
-               *linePtr = cp;
-               return (argLen);
-       }
-}
-
-/**
- * CondDoDefined
- *     Handle the 'defined' function for conditionals.
- *
- * Results:
- *     true if the given variable is defined.
- */
-static bool
-CondDoDefined(Parser *parser __unused, int argLen, char *arg)
-{
-       char    savec = arg[argLen];
-       bool    result;
-
-       arg[argLen] = '\0';
-       if (Var_Value(arg, VAR_CMD) != NULL) {
-               result = true;
-       } else {
-               result = false;
-       }
-       arg[argLen] = savec;
-       return (result);
-}
-
-/**
- * CondDoMake
- *     Handle the 'make' function for conditionals.
- *
- * Results:
- *     true if the given target is being made.
- */
-static bool
-CondDoMake(Parser *parser, int argLen, char *arg)
-{
-       char    savec = arg[argLen];
-       bool    result;
-       const LstNode *ln;
-
-       arg[argLen] = '\0';
-       result = false;
-       LST_FOREACH(ln, parser->create) {
-               if (Str_Match(Lst_Datum(ln), arg)) {
-                       result = true;
-                       break;
-               }
-       }
-       arg[argLen] = savec;
-       return (result);
-}
-
-/**
- * CondDoExists
- *     See if the given file exists.
- *
- * Results:
- *     true if the file exists and false if it does not.
- */
-static bool
-CondDoExists(Parser *parser __unused, int argLen, char *arg)
-{
-       char    savec = arg[argLen];
-       bool    result;
-       char    *path;
-
-       arg[argLen] = '\0';
-       path = Path_FindFile(arg, &dirSearchPath);
-       if (path != NULL) {
-               result = true;
-               free(path);
-       } else {
-               result = false;
-       }
-       arg[argLen] = savec;
-       return (result);
-}
-
-/**
- * CondDoTarget
- *     See if the given node exists and is an actual target.
- *
- * Results:
- *     true if the node exists as a target and false if it does not.
- */
-static bool
-CondDoTarget(Parser *parser __unused, int argLen, char *arg)
-{
-       char    savec = arg[argLen];
-       bool    result;
-       GNode   *gn;
-
-       arg[argLen] = '\0';
-       gn = Targ_FindNode(arg, TARG_NOCREATE);
-       if ((gn != NULL) && !OP_NOP(gn->type)) {
-               result = true;
-       } else {
-               result = false;
-       }
-       arg[argLen] = savec;
-       return (result);
-}
-
-/**
- * CondCvtArg
- *     Convert the given number into a double. If the number begins
- *     with 0x, it is interpreted as a hexadecimal integer
- *     and converted to a double from there. All other strings just have
- *     strtod called on them.
- *
- * Results:
- *     Sets 'value' to double value of string.
- *     Returns address of the first character after the last valid
- *     character of the converted number.
- *
- * Side Effects:
- *     Can change 'value' even if string is not a valid number.
- */
-static char *
-CondCvtArg(char *str, double *value)
-{
-
-       if ((*str == '0') && (str[1] == 'x')) {
-               long i;
-
-               for (str += 2, i = 0; ; str++) {
-                       int x;
-
-                       if (isdigit((unsigned char)*str))
-                               x  = *str - '0';
-                       else if (isxdigit((unsigned char)*str))
-                               x = 10 + *str -
-                                   isupper((unsigned char)*str) ? 'A' : 'a';
-                       else {
-                               *value = (double)i;
-                               return (str);
-                       }
-                       i = (i << 4) + x;
-               }
-
-       } else {
-               char *eptr;
-
-               *value = strtod(str, &eptr);
-               return (eptr);
-       }
-}
-
-/**
- * CondToken
- *     Return the next token from the input.
- *
- * Results:
- *     A Token for the next lexical token in the stream.
- *
- * Side Effects:
- *     condPushback will be set back to None if it is used.
- */
-static Token
-CondToken(Parser *parser, bool doEval)
-{
-       Token   t;
-
-       if (condPushBack != None) {
-               t = condPushBack;
-               condPushBack = None;
-               return (t);
-       }
-
-       while (*condExpr == ' ' || *condExpr == '\t') {
-               condExpr++;
-       }
-
-       switch (*condExpr) {
-       case OPEN_PAREN:
-               t = LParen;
-               condExpr++;
-               break;
-       case CLOSE_PAREN:
-               t = RParen;
-               condExpr++;
-               break;
-       case '|':
-               if (condExpr[1] == '|') {
-                       condExpr++;
-               }
-               condExpr++;
-               t = Or;
-               break;
-       case '&':
-               if (condExpr[1] == '&') {
-                       condExpr++;
-               }
-               condExpr++;
-               t = And;
-               break;
-       case '!':
-               t = Not;
-               condExpr++;
-               break;
-       case '\n':
-       case '\0':
-               t = EndOfFile;
-               break;
-       case '$':{
-                       char            *lhs;
-                       const char      *op;
-                       char            *rhs;
-                       char            zero[] = "0";
-                       size_t          varSpecLen = 0;
-                       bool            doFree;
-
-                       /*
-                        * Parse the variable spec and skip over it, saving
-                        * its value in lhs.
-                        */
-                       t = Err;
-                       lhs = Var_Parse(condExpr, VAR_CMD, doEval,
-                                       &varSpecLen, &doFree);
-                       if (lhs == var_Error) {
-                               /*
-                                * Even if !doEval, we still report syntax
-                                * errors, which is what getting var_Error
-                                * back with !doEval means.
-                                */
-                               return (Err);
-                       }
-                       condExpr += varSpecLen;
-
-                       if (!isspace((unsigned char)*condExpr) &&
-                           strchr("!=><", *condExpr) == NULL) {
-                               Buffer *buf;
-
-                               buf = Buf_Init(0);
-
-                               Buf_Append(buf, lhs);
-
-                               if (doFree)
-                                       free(lhs);
-
-                               for (; *condExpr &&
-                                    !isspace((unsigned char)*condExpr);
-                                    condExpr++)
-                                       Buf_AddByte(buf, *condExpr);
-
-                               Buf_AddByte(buf, '\0');
-                               lhs = Buf_Data(buf);
-                               Buf_Destroy(buf, false);
-
-                               doFree = true;
-                       }
-
-                       /*
-                        * Skip whitespace to get to the operator
-                        */
-                       while (isspace((unsigned char)*condExpr))
-                               condExpr++;
-
-                       /*
-                        * Make sure the operator is a valid one. If it isn't
-                        * a known relational operator, pretend we got a != 0
-                        * comparison.
-                        */
-                       op = condExpr;
-                       switch (*condExpr) {
-                       case '!':
-                       case '=':
-                       case '<':
-                       case '>':
-                               if (condExpr[1] == '=') {
-                                       condExpr += 2;
-                               } else {
-                                       condExpr += 1;
-                               }
-                               while (isspace((unsigned char)*condExpr)) {
-                                       condExpr++;
-                               }
-                               if (*condExpr == '\0') {
-                                       Parse_Error(PARSE_WARNING,
-                                            "Missing right-hand-side of operator");
-                                       goto error;
-                               }
-                               rhs = condExpr;
-                               break;
-                       default:
-                               op = "!=";
-                               rhs = zero;
-                               break;
-                       }
-
-                       if (*rhs == '"') {
-                               /*
-                                * Doing a string comparison. Only allow ==
-                                * and != for * operators.
-                                */
-                               char   *string;
-                               char   *cp, *cp2;
-                               int     qt;
-                               Buffer *buf;
-
-               do_string_compare:
-                               if (((*op != '!') && (*op != '=')) ||
-                                   (op[1] != '=')) {
-                                       Parse_Error(PARSE_WARNING,
-                                       "String comparison operator should "
-                                                   "be either == or !=");
-                                       goto error;
-                               }
-                               buf = Buf_Init(0);
-                               qt = *rhs == '"' ? 1 : 0;
-
-                               for (cp = &rhs[qt];
-                                    ((qt && (*cp != '"')) ||
-                                   (!qt && strchr(" \t)", *cp) == NULL)) &&
-                                    (*cp != '\0'); cp++) {
-                                       if ((*cp == '\\') && (cp[1] != '\0')) {
-                                               /*
-                                                * Backslash escapes things
-                                                * -- skip over next
-                                                * character,                                                    *
-                                                * if it exists.
-                                                */
-                                               cp++;
-                                               Buf_AddByte(buf, *cp);
-
-                                       } else if (*cp == '$') {
-                                               size_t  len = 0;
-                                               bool    freeIt;
-
-                                               cp2 = Var_Parse(cp, VAR_CMD,
-                                                    doEval, &len, &freeIt);
-                                               if (cp2 != var_Error) {
-                                                       Buf_Append(buf, cp2);
-                                                       if (freeIt) {
-                                                               free(cp2);
-                                                       }
-                                                       cp += len - 1;
-                                               } else {
-                                                       Buf_AddByte(buf, *cp);
-                                               }
-                                       } else {
-                                               Buf_AddByte(buf, *cp);
-                                       }
-                               }
-
-                               string = Buf_Peel(buf);
-
-                               DEBUGF(COND, ("lhs = \"%s\", rhs = \"%s\", "
-                                          "op = %.2s\n", lhs, string, op));
-                               /*
-                                * Null-terminate rhs and perform the
-                                * comparison. t is set to the result.
-                                */
-                               if (*op == '=') {
-                                       t = strcmp(lhs, string) ? False : True;
-                               } else {
-                                       t = strcmp(lhs, string) ? True : False;
-                               }
-                               free(string);
-                               if (rhs == condExpr) {
-                                       if (*cp == '\0' || (!qt && *cp == CLOSE_PAREN))
-                                               condExpr = cp;
-                                       else
-                                               condExpr = cp + 1;
-                               }
-                       } else {
-                               /*
-                                * rhs is either a float or an integer.
-                                * Convert both the lhs and the rhs to a
-                                * double and compare the two.
-                                */
-                               double  left, right;
-                               char   *string;
-
-                               if (*CondCvtArg(lhs, &left) != '\0')
-                                       goto do_string_compare;
-                               if (*rhs == '$') {
-                                       size_t  len = 0;
-                                       bool    freeIt;
-
-                                       string = Var_Parse(rhs, VAR_CMD, doEval,
-                                                          &len, &freeIt);
-                                       if (string == var_Error) {
-                                               right = 0.0;
-                                       } else {
-                                               if (*CondCvtArg(string,
-                                                         &right) != '\0') {
-                                                       if (freeIt)
-                                                               free(string);
-                                                       goto do_string_compare;
-                                               }
-                                               if (freeIt)
-                                                       free(string);
-                                               if (rhs == condExpr)
-                                                       condExpr += len;
-                                       }
-                               } else {
-                                       char   *c = CondCvtArg(rhs, &right);
-
-                                       if (c == rhs)
-                                               goto do_string_compare;
-                                       if (rhs == condExpr) {
-                                               /*
-                                                * Skip over the right-hand
-                                                * side
-                                                */
-                                               condExpr = c;
-                                       }
-                               }
-
-                               DEBUGF(COND, ("left = %f, right = %f, "
-                                          "op = %.2s\n", left, right, op));
-                               switch (op[0]) {
-                               case '!':
-                                       if (op[1] != '=') {
-                                               Parse_Error(PARSE_WARNING,
-                                                       "Unknown operator");
-                                               goto error;
-                                       }
-                                       t = (left != right ? True : False);
-                                       break;
-                               case '=':
-                                       if (op[1] != '=') {
-                                               Parse_Error(PARSE_WARNING,
-                                                       "Unknown operator");
-                                               goto error;
-                                       }
-                                       t = (left == right ? True : False);
-                                       break;
-                               case '<':
-                                       if (op[1] == '=') {
-                                               t = (left <= right ? True : False);
-                                       } else {
-                                               t = (left < right ? True : False);
-                                       }
-                                       break;
-                               case '>':
-                                       if (op[1] == '=') {
-                                               t = (left >= right ? True : False);
-                                       } else {
-                                               t = (left > right ? True : False);
-                                       }
-                                       break;
-                               default:
-                                       break;
-                               }
-                       }
-       error:
-                       if (doFree)
-                               free(lhs);
-                       break;
-               }
-
-       default:{
-                       CondProc *evalProc;
-                       bool    invert = false;
-                       char   *arg;
-                       int     arglen;
-
-                       if (strncmp(condExpr, "defined", 7) == 0) {
-                               /*
-                                * Use CondDoDefined to evaluate the argument
-                                * and CondGetArg to extract the argument
-                                * from the 'function call'.
-                                */
-                               evalProc = CondDoDefined;
-                               condExpr += 7;
-                               arglen = CondGetArg(&condExpr, &arg,
-                                                   "defined", true);
-                               if (arglen == 0) {
-                                       condExpr -= 7;
-                                       goto use_default;
-                               }
-                       } else if (strncmp(condExpr, "make", 4) == 0) {
-                               /*
-                                * Use CondDoMake to evaluate the argument
-                                * and CondGetArg to extract the argument
-                                * from the 'function call'.
-                                */
-                               evalProc = CondDoMake;
-                               condExpr += 4;
-                               arglen = CondGetArg(&condExpr, &arg,
-                                                   "make", true);
-                               if (arglen == 0) {
-                                       condExpr -= 4;
-                                       goto use_default;
-                               }
-                       } else if (strncmp(condExpr, "exists", 6) == 0) {
-                               /*
-                                * Use CondDoExists to evaluate the argument
-                                * and CondGetArg to extract the argument
-                                * from the 'function call'.
-                                */
-                               evalProc = CondDoExists;
-                               condExpr += 6;
-                               arglen = CondGetArg(&condExpr, &arg,
-                                                   "exists", true);
-                               if (arglen == 0) {
-                                       condExpr -= 6;
-                                       goto use_default;
-                               }
-                       } else if (strncmp(condExpr, "empty", 5) == 0) {
-                               /*
-                                * Use Var_Parse to parse the spec in parens
-                                * and return True if the resulting string is
-                                * empty.
-                                */
-                               size_t  length;
-                               bool    doFree;
-                               char   *val;
-
-                               condExpr += 5;
-
-                               for (arglen = 0;
-                                    condExpr[arglen] != OPEN_PAREN &&
-                                    condExpr[arglen] != '\0'; arglen += 1)
-                                       continue;
-
-                               if (condExpr[arglen] != '\0') {
-                                       length = 0;
-                                       val = Var_Parse(&condExpr[arglen - 1],
-                                         VAR_CMD, false, &length, &doFree);
-                                       if (val == var_Error) {
-                                               t = Err;
-                                       } else {
-                                               /*
-                                                * A variable is empty when
-                                                * it just contains spaces...
-                                                * 4/15/92, christos
-                                                */
-                                               char   *p;
-
-                                               for (p = val;
-                                                    *p &&
-                                                isspace((unsigned char)*p);
-                                                    p++)
-                                                       continue;
-                                               t = (*p == '\0') ? True : False;
-                                       }
-                                       if (doFree) {
-                                               free(val);
-                                       }
-                                       /*
-                                        * Advance condExpr to beyond the
-                                        * closing ). Note that we subtract
-                                        * one from arglen + length b/c
-                                        * length is calculated from
-                                        * condExpr[arglen - 1].
-                                        */
-                                       condExpr += arglen + length - 1;
-                               } else {
-                                       condExpr -= 5;
-                                       goto use_default;
-                               }
-                               break;
-
-                       } else if (strncmp(condExpr, "target", 6) == 0) {
-                               /*
-                                * Use CondDoTarget to evaluate the argument
-                                * and CondGetArg to extract the argument
-                                * from the 'function call'.
-                                */
-                               evalProc = CondDoTarget;
-                               condExpr += 6;
-                               arglen = CondGetArg(&condExpr, &arg,
-                                                   "target", true);
-                               if (arglen == 0) {
-                                       condExpr -= 6;
-                                       goto use_default;
-                               }
-                       } else {
-                               /*
-                                * The symbol is itself the argument to the
-                                * default function. We advance condExpr to
-                                * the end of the symbol by hand (the next
-                                * whitespace, closing paren or binary
-                                * operator) and set to invert the evaluation
-                                * function if condInvert is true.
-                                */
-               use_default:
-                               invert = condInvert;
-                               evalProc = condDefProc;
-                               arglen = CondGetArg(&condExpr, &arg, "", false);
-                       }
-
-                       /*
-                        * Evaluate the argument using the set function. If
-                        * invert is true, we invert the sense of the
-                        * function.
-                        */
-                       t = (!doEval || evalProc(parser, arglen, arg) ?
-                            (invert ? False : True) :
-                            (invert ? True : False));
-                       free(arg);
-                       break;
-               }
-       }
-       return (t);
-}
-
-/**
- * CondT
- *     Parse a single term in the expression. This consists of a terminal
- *     symbol or Not and a terminal symbol (not including the binary
- *     operators):
- *         T -> defined(variable) | make(target) | exists(file) | symbol
- *         T -> ! T | ( E )
- *
- * Results:
- *     True, False or Err.
- *
- * Side Effects:
- *     Tokens are consumed.
- */
-static Token
-CondT(Parser *parser, bool doEval)
-{
-       Token   t;
-
-       t = CondToken(parser, doEval);
-       if (t == EndOfFile) {
-               /*
-                * If we reached the end of the expression, the expression
-                * is malformed...
-                */
-               t = Err;
-       } else if (t == LParen) {
-               /*
-                * T -> ( E )
-                */
-               t = CondE(parser, doEval);
-               if (t != Err) {
-                       if (CondToken(parser, doEval) != RParen) {
-                               t = Err;
-                       }
-               }
-       } else if (t == Not) {
-               t = CondT(parser, doEval);
-               if (t == True) {
-                       t = False;
-               } else if (t == False) {
-                       t = True;
-               }
-       }
-       return (t);
-}
-
-/**
- * CondF --
- *     Parse a conjunctive factor (nice name, wot?)
- *         F -> T && F | T
- *
- * Results:
- *     True, False or Err
- *
- * Side Effects:
- *     Tokens are consumed.
- */
-static Token
-CondF(Parser *parser, bool doEval)
-{
-       Token   l, o;
-
-       l = CondT(parser, doEval);
-       if (l != Err) {
-               o = CondToken(parser, doEval);
-
-               if (o == And) {
-                       /*
-                        * F -> T && F
-                        *
-                        * If T is False, the whole thing will be False, but
-                        * we have to parse the r.h.s. anyway (to throw it
-                        * away). If T is True, the result is the r.h.s.,
-                        * be it an Err or no.
-                        */
-                       if (l == True) {
-                               l = CondF(parser, doEval);
-                       } else {
-                               CondF(parser, false);
-                       }
-               } else {
-                       /*
-                        * F -> T
-                        */
-                       CondPushBack(o);
-               }
-       }
-       return (l);
-}
-
-/**
- * CondE --
- *     Main expression production.
- *         E -> F || E | F
- *
- * Results:
- *     True, False or Err.
- *
- * Side Effects:
- *     Tokens are, of course, consumed.
- */
-static Token
-CondE(Parser *parser, bool doEval)
-{
-       Token   l, o;
-
-       l = CondF(parser, doEval);
-       if (l != Err) {
-               o = CondToken(parser, doEval);
-
-               if (o == Or) {
-                       /*
-                        * E -> F || E
-                        *
-                        * A similar thing occurs for ||, except that here we
-                        * make sure the l.h.s. is False before we bother to
-                        * evaluate the r.h.s. Once again, if l is False, the
-                        * result is the r.h.s. and once again if l is True,
-                        * we parse the r.h.s. to throw it away.
-                        */
-                       if (l == False) {
-                               l = CondE(parser, doEval);
-                       } else {
-                               CondE(parser, false);
-                       }
-               } else {
-                       /*
-                        * E -> F
-                        */
-                       CondPushBack(o);
-               }
-       }
-       return (l);
-}
-
-/**
- * Cond_If
- *     Handle .if<X> and .elif<X> directives.
- *     This function is called even when we're skipping.
- */
-void
-Cond_If(Parser *parser, char *line, int code, int lineno)
-{
-       const struct If *ifp;
-       bool value;
-
-       ifp = &ifs[code];
-
-       if (ifp->isElse) {
-               if (condTop == MAXIF) {
-                       Parse_Error(PARSE_FATAL, "if-less elif");
-                       return;
-               }
-               if (skipIfLevel != 0) {
-                       /*
-                        * If skipping this conditional, just ignore
-                        * the whole thing. If we don't, the user
-                        * might be employing a variable that's
-                        * undefined, for which there's an enclosing
-                        * ifdef that we're skipping...
-                        */
-                       skipIfLineno[skipIfLevel - 1] = lineno;
-                       return;
-               }
-
-       } else if (skipLine) {
-               /*
-                * Don't even try to evaluate a conditional that's
-                * not an else if we're skipping things...
-                */
-               skipIfLineno[skipIfLevel] = lineno;
-               skipIfLevel += 1;
-               return;
-       }
-
-       /*
-        * Initialize file-global variables for parsing
-        */
-       condDefProc = ifp->defProc;
-       condInvert = ifp->doNot;
-
-       while (*line == ' ' || *line == '\t') {
-               line++;
-       }
-
-       condExpr = line;
-       condPushBack = None;
-
-       switch (CondE(parser, true)) {
-         case True:
-               if (CondToken(parser, true) != EndOfFile)
-                       goto err;
-               value = true;
-               break;
-
-         case False:
-               if (CondToken(parser, true) != EndOfFile)
-                       goto err;
-               value = false;
-               break;
-
-         case Err:
-  err:         Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", line);
-               return;
-
-         default:
-               abort();
-       }
-
-       if (!ifp->isElse) {
-               /* push this value */
-               condTop -= 1;
-
-       } else if (skipIfLevel != 0 || condStack[condTop]) {
-               /*
-                * If this is an else-type conditional, it should only take
-                * effect if its corresponding if was evaluated and false.
-                * If its if was true or skipped, we return COND_SKIP (and
-                * start skipping in case we weren't already), leaving the
-                * stack unmolested so later elif's don't screw up...
-                */
-               skipLine = true;
-               return;
-       }
-
-       if (condTop < 0) {
-               /*
-                * This is the one case where we can definitely proclaim a fatal
-                * error. If we don't, we're hosed.
-                */
-               Parse_Error(PARSE_FATAL, "Too many nested if's. %d max.",MAXIF);
-               return;
-       }
-
-       /* push */
-       condStack[condTop] = value;
-       condLineno[condTop] = lineno;
-       skipLine = !value;
-}
-
-/**
- * Cond_Else
- *     Handle .else statement.
- */
-void
-Cond_Else(Parser *parser __unused, char *line __unused, int code __unused, int lineno __unused)
-{
-
-       while (isspace((u_char)*line))
-               line++;
-
-       if (*line != '\0' && (warn_flags & WARN_DIRSYNTAX)) {
-               Parse_Error(PARSE_WARNING, "junk after .else ignored '%s'",
-                   line);
-       }
-
-       if (condTop == MAXIF) {
-               Parse_Error(PARSE_FATAL, "if-less else");
-               return;
-       }
-       if (skipIfLevel != 0)
-               return;
-
-       if (skipIfLevel != 0 || condStack[condTop]) {
-               /*
-                * An else should only take effect if its corresponding if was
-                * evaluated and false.
-                * If its if was true or skipped, we return COND_SKIP (and
-                * start skipping in case we weren't already), leaving the
-                * stack unmolested so later elif's don't screw up...
-                * XXX How does this work with two .else's?
-                */
-               skipLine = true;
-               return;
-       }
-
-       /* inverse value */
-       condStack[condTop] = !condStack[condTop];
-       skipLine = !condStack[condTop];
-}
-
-/**
- * Cond_Endif
- *     Handle .endif statement.
- */
-void
-Cond_Endif(Parser *parser __unused, char *line __unused, int code __unused, int lineno __unused)
-{
-
-       while (isspace((u_char)*line))
-               line++;
-
-       if (*line != '\0' && (warn_flags & WARN_DIRSYNTAX)) {
-               Parse_Error(PARSE_WARNING, "junk after .endif ignored '%s'",
-                   line);
-       }
-
-       /*
-        * End of a conditional section. If skipIfLevel is non-zero,
-        * that conditional was skipped, so lines following it should
-        * also be skipped. Hence, we return COND_SKIP. Otherwise,
-        * the conditional was read so succeeding lines should be
-        * parsed (think about it...) so we return COND_PARSE, unless
-        * this endif isn't paired with a decent if.
-        */
-       if (skipIfLevel != 0) {
-               skipIfLevel -= 1;
-               return;
-       }
-
-       if (condTop == MAXIF) {
-               Parse_Error(PARSE_FATAL, "if-less endif");
-               return;
-       }
-
-       /* pop */
-       skipLine = false;
-       condTop += 1;
-}
-
-/**
- * Cond_End
- *     Make sure everything's clean at the end of a makefile.
- *
- * Side Effects:
- *     Parse_Error will be called if open conditionals are around.
- */
-void
-Cond_End(Parser *parser __unused, char *line __unused, int code __unused, int lineno __unused)
-{
-       int level;
-
-       if (condTop != MAXIF) {
-               Parse_Error(PARSE_FATAL, "%d open conditional%s:",
-                   MAXIF - condTop + skipIfLevel,
-                   MAXIF - condTop + skipIfLevel== 1 ? "" : "s");
-
-               for (level = skipIfLevel; level > 0; level--)
-                       Parse_Error(PARSE_FATAL, "\t%*sat line %d (skipped)",
-                           MAXIF - condTop + level + 1, "",
-                           skipIfLineno[level - 1]);
-               for (level = condTop; level < MAXIF; level++)
-                       Parse_Error(PARSE_FATAL, "\t%*sat line %d "
-                           "(evaluated to %s)", MAXIF - level + skipIfLevel,
-                           "", condLineno[level],
-                           condStack[level] ? "true" : "false");
-       }
-       condTop = MAXIF;
-}
diff --git a/usr.bin/make/cond.h b/usr.bin/make/cond.h
deleted file mode 100644 (file)
index eef3c03..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*-
- * Copyright (c) 1988, 1989, 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- * Copyright (c) 1989 by Berkeley Softworks
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Adam de Boor.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $DragonFly: src/usr.bin/make/cond.h,v 1.7 2005/08/03 19:48:44 okumoto Exp $
- */
-
-#ifndef cond_h_6e96ad7c
-#define        cond_h_6e96ad7c
-
-#include <stdbool.h>
-
-#include "parse.h"
-
-/*
- * Values returned by Cond_Eval.
- */
-#define        COND_PARSE      0       /* Parse the next lines */
-#define        COND_SKIP       1       /* Skip the next lines */
-#define        COND_INVALID    2       /* Not a conditional statement */
-
-enum {
-       COND_IF,
-       COND_IFDEF,
-       COND_IFNDEF,
-       COND_IFMAKE,
-       COND_IFNMAKE,
-       COND_ELSE,
-       COND_ELIF,
-       COND_ELIFDEF,
-       COND_ELIFNDEF,
-       COND_ELIFMAKE,
-       COND_ELIFNMAKE,
-       COND_ENDIF,
-};
-
-DirectiveHandler Cond_If;
-DirectiveHandler Cond_Else;
-DirectiveHandler Cond_Endif;
-DirectiveHandler Cond_End;
-
-extern bool skipLine;
-
-#endif /* cond_h_6e96ad7c */
diff --git a/usr.bin/make/config.h b/usr.bin/make/config.h
deleted file mode 100644 (file)
index 1060c69..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*-
- * Copyright (c) 1988, 1989, 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- * Copyright (c) 1988, 1989 by Adam de Boor
- * Copyright (c) 1989 by Berkeley Softworks
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Adam de Boor.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- *     from: @(#)config.h      8.1 (Berkeley) 6/6/93
- * $FreeBSD: src/usr.bin/make/config.h,v 1.16 2005/02/01 10:50:35 harti Exp $
- * $DragonFly: src/usr.bin/make/config.h,v 1.13 2005/08/24 00:09:02 okumoto Exp $
- */
-
-#ifndef config_h_efe0765e
-#define        config_h_efe0765e
-
-/*
- * INCLUDES
- * LIBRARIES
- *     These control the handling of the .INCLUDES and .LIBS variables.
- *     If INCLUDES is defined, the .INCLUDES variable will be filled
- *     from the search paths of those suffixes which are marked by
- *     .INCLUDES dependency lines. Similarly for LIBRARIES and .LIBS
- *     See suff.c for more details.
- */
-#define        INCLUDES
-#define        LIBRARIES
-
-/*
- * RECHECK
- *     If defined, Make_Update will check a target for its current
- *     modification time after it has been re-made, setting it to the
- *     starting time of the make only if the target still doesn't exist.
- *     Unfortunately, under NFS the modification time often doesn't
- *     get updated in time, so a target will appear to not have been
- *     re-made, causing later targets to appear up-to-date. On systems
- *     that don't have this problem, you should defined this. Under
- *     NFS you probably should not, unless you aren't exporting jobs.
- */
-#define        RECHECK
-
-/*
- * SYSVINCLUDE
- *     Recognize system V like include directives [include "filename"]
- */
-#define        SYSVINCLUDE
-
-/*
- * SUNSHCMD
- *     Recognize SunOS and Solaris:
- *             VAR :sh= CMD    # Assign VAR to the command substitution of CMD
- *             ${VAR:sh}       # Return the command substitution of the value
- *                             # of ${VAR}
- */
-#define        SUNSHCMD
-
-#endif /* config_h_efe0765e */
diff --git a/usr.bin/make/dir.c b/usr.bin/make/dir.c
deleted file mode 100644 (file)
index 29ed33e..0000000
+++ /dev/null
@@ -1,1140 +0,0 @@
-/*-
- * Copyright (c) 1988, 1989, 1990, 1993
- *     The Regents of the University of California.  All rights reserved.
- * Copyright (c) 1988, 1989 by Adam de Boor
- * Copyright (c) 1989 by Berkeley Softworks
- * All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Adam de Boor.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *     This product includes software developed by the University of
- *     California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * @(#)dir.c   8.2 (Berkeley) 1/2/94
- * $FreeBSD: src/usr.bin/make/dir.c,v 1.47 2005/02/04 07:50:59 harti Exp $
- * $DragonFly: src/usr.bin/make/dir.c,v 1.44 2005/11/05 15:35:10 swildner Exp $
- */
-
-/*-
- * dir.c --
- *     Directory searching using wildcards and/or normal names...
- *     Used both for source wildcarding in the Makefile and for finding
- *     implicit sources.
- *
- * The interface for this module is:
- *     Dir_Init        Initialize the module.
- *
- *     Dir_HasWildcards Returns true if the name given it needs to
- *                     be wildcard-expanded.
- *
- *     Path_Expand     Given a pattern and a path, return a Lst of names
- *                     which match the pattern on the search path.
- *
- *     Path_FindFile   Searches for a file on a given search path.
- *                     If it exists, the entire path is returned.
- *                     Otherwise NULL is returned.
- *
- *     Dir_MTime       Return the modification time of a node. The file
- *                     is searched for along the default search path.
- *                     The path and mtime fields of the node are filled in.
- *
- *     Path_AddDir     Add a directory to a search path.
- *
- *     Dir_MakeFlags   Given a search path and a command flag, create
- *                     a string with each of the directories in the path
- *                     preceded by the command flag and all of them
- *                     separated by a space.
- *
- *     Dir_Destroy     Destroy an element of a search path. Frees up all
- *                     things that can be freed for the element as long
- *                     as the element is no longer referenced by any other
- *                     search path.
- *
- *     Dir_ClearPath   Resets a search path to the empty list.
- *
- * For debugging:
- *     Dir_PrintDirectories    Print stats about the directory cache.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <err.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "arch.h"
-#include "dir.h"
-#include "globals.h"
-#include "GNode.h"
-#include "hash.h"
-#include "lst.h"
-#include "make.h"
-#include "str.h"
-#include "targ.h"
-#include "util.h"
-
-/*
- *     A search path consists of a list of Dir structures. A Dir structure
- *     has in it the name of the directory and a hash table of all the files
- *     in the directory. This is used to cut down on the number of system
- *     calls necessary to find implicit dependents and their like. Since
- *     these searches are made before any actions are taken, we need not
- *     worry about the directory changing due to creation commands. If this
- *     hampers the style of some makefiles, they must be changed.
- *
- *     A list of all previously-read directories is kept in the
- *     openDirectories list. This list is checked first before a directory
- *     is opened.
- *
- *     The need for the caching of whole directories is brought about by
- *     the multi-level transformation code in suff.c, which tends to search
- *     for far more files than regular make does. In the initial
- *     implementation, the amount of time spent performing "stat" calls was
- *     truly astronomical. The problem with hashing at the start is,
- *     of course, that pmake doesn't then detect changes to these directories
- *     during the course of the make. Three possibilities suggest themselves:
- *
- *         1) just use stat to test for a file's existence. As mentioned
- *            above, this is very inefficient due to the number of checks
- *            engendered by the multi-level transformation code.
- *         2) use readdir() and company to search the directories, keeping
- *            them open between checks. I have tried this and while it
- *            didn't slow down the process too much, it could severely
- *            affect the amount of parallelism available as each directory
- *            open would take another file descriptor out of play for
- *            handling I/O for another job. Given that it is only recently
- *            that UNIX OS's have taken to allowing more than 20 or 32
- *            file descriptors for a process, this doesn't seem acceptable
- *            to me.
- *         3) record the mtime of the directory in the Dir structure and
- *            verify the directory hasn't changed since the contents were
- *            hashed. This will catch the creation or deletion of files,
- *            but not the updating of files. However, since it is the
- *            creation and deletion that is the problem, this could be
- *            a good thing to do. Unfortunately, if the directory (say ".")
- *            were fairly large and changed fairly frequently, the constant
- *            rehashing could seriously degrade performance. It might be
- *            good in such cases to keep track of the number of rehashes
- *            and if the number goes over a (small) limit, resort to using
- *            stat in its place.
- *
- *     An additional thing to consider is that pmake is used primarily
- *     to create C programs and until recently pcc-based compilers refused
- *     to allow you to specify where the resulting object file should be
- *     placed. This forced all objects to be created in the current
- *     directory. This isn't meant as a full excuse, just an explanation of
- *     some of the reasons for the caching used here.
- *
- *     One more note: the location of a target's file is only performed
- *     on the downward traversal of the graph and then only for terminal
- *     nodes in the graph. This could be construed as wrong in some cases,
- *     but prevents inadvertent modification of files when the "installed"
- *     directory for a file is provided in the search path.
- *
- *     Another data structure maintained by this module is an mtime
- *     cache used when the searching of cached directories fails to find
- *     a file. In the past, Path_FindFile would simply perform an access()
- *     call in such a case to determine if the file could be found using
- *     just the name given. When this hit, however, all that was gained
- *     was the knowledge that the file existed. Given that an access() is
- *     essentially a stat() without the copyout() call, and that the same
- *     filesystem overhead would have to be incurred in Dir_MTime, it made
- *     sense to replace the access() with a stat() and record the mtime
- *     in a cache for when Dir_MTime was actually called.
- */
-
-typedef struct Dir {
-       char    *name;          /* Name of directory */
-       int     refCount;       /* No. of paths with this directory */
-       int     hits;           /* No. of times a file has been found here */
-       Hash_Table files;       /* Hash table of files in directory */
-       TAILQ_ENTRY(Dir) link;  /* allDirs link */
-} Dir;
-
-/*
- * A path is a list of pointers to directories. These directories are
- * reference counted so a directory can be on more than one path.
- */
-struct PathElement {
-       struct Dir      *dir;   /* pointer to the directory */
-       TAILQ_ENTRY(PathElement) link;  /* path link */
-};
-
-/* main search path */
-struct Path                    dirSearchPath;
-
-/* the list of all open directories */
-static TAILQ_HEAD(, Dir)       openDirectories;
-
-/*
- * Variables for gathering statistics on the efficiency of the hashing
- * mechanism.
- */
-static int hits;       /* Found in directory cache */
-static int misses;      /* Sad, but not evil misses */
-static int nearmisses; /* Found under search path */
-static int bigmisses;  /* Sought by itself */
-
-static Dir *dot;           /* contents of current directory */
-
-/* Results of doing a last-resort stat in Path_FindFile --
- * if we have to go to the system to find the file, we might as well
- * have its mtime on record.
- * XXX: If this is done way early, there's a chance other rules will
- * have already updated the file, in which case we'll update it again.
- * Generally, there won't be two rules to update a single file, so this
- * should be ok, but...
- */
-static Hash_Table mtimes;
-
-/**
- * initialize things for this module
- *     add the "." directory
- *     add curdir if it is not the same as objdir
- */
-void
-Dir_Init(void)
-{
-
-       Hash_InitTable(&mtimes, 0);
-       TAILQ_INIT(&dirSearchPath);
-       TAILQ_INIT(&openDirectories);
-}
-
-/**
- * add the "." directory
- * add curdir if it is not the same as objdir
- */
-void
-Dir_CurObj(const char curdir[], const char objdir[])
-{
-
-       dot = Path_AddDir(NULL, ".");
-       if (dot == NULL)
-               err(1, "cannot open current directory");
-
-       /*
-        * We always need to have dot around, so we increment its
-        * reference count to make sure it's not destroyed.
-        */
-       dot->refCount += 1;
-
-       if (strcmp(objdir, curdir) != 0)
-               Path_AddDir(&dirSearchPath, curdir);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * Dir_HasWildcards  --
- *     See if the given name has any wildcard characters in it.
- *
- * Results:
- *     returns true if the word should be expanded, false otherwise
- *
- * Side Effects:
- *     none
- *-----------------------------------------------------------------------
- */
-bool
-Dir_HasWildcards(const char *name)
-{
-       const char *cp;
-       int wild = 0, brace = 0, bracket = 0;
-
-       for (cp = name; *cp; cp++) {
-               switch (*cp) {
-               case '{':
-                       brace++;
-                       wild = 1;
-                       break;
-               case '}':
-                       brace--;
-                       break;
-               case '[':
-                       bracket++;
-                       wild = 1;
-                       break;
-               case ']':
-                       bracket--;
-                       break;
-               case '?':
-               case '*':
-                       wild = 1;
-                       break;
-               default:
-                       break;
-               }
-       }
-       return (wild && bracket == 0 && brace == 0);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * DirMatchFiles --
- *     Given a pattern and a Dir structure, see if any files
- *     match the pattern and add their names to the 'expansions' list if
- *     any do. This is incomplete -- it doesn't take care of patterns like
- *     src / *src / *.c properly (just *.c on any of the directories), but it
- *     will do for now.
- *
- * Results:
- *     Always returns 0
- *
- * Side Effects:
- *     File names are added to the expansions lst. The directory will be
- *     fully hashed when this is done.
- *-----------------------------------------------------------------------
- */
-static int
-DirMatchFiles(const char *pattern, const Dir *p, Lst *expansions)
-{
-       Hash_Search search;     /* Index into the directory's table */
-       Hash_Entry *entry;      /* Current entry in the table */
-       bool isDot;             /* true if the directory being searched is . */
-
-       isDot = (*p->name == '.' && p->name[1] == '\0');
-
-       for (entry = Hash_EnumFirst(&p->files, &search);
-           entry != NULL;
-           entry = Hash_EnumNext(&search)) {
-               /*
-                * See if the file matches the given pattern. Note we follow
-                * the UNIX convention that dot files will only be found if
-                * the pattern begins with a dot (note also that as a side
-                * effect of the hashing scheme, .* won't match . or ..
-                * since they aren't hashed).
-                */
-               if (Str_Match(entry->name, pattern) &&
-                   ((entry->name[0] != '.') ||
-                   (pattern[0] == '.'))) {
-                       Lst_AtEnd(expansions, (isDot ? estrdup(entry->name) :
-                           str_concat(p->name, '/', entry->name)));
-               }
-       }
-       return (0);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * DirExpandCurly --
- *     Expand curly braces like the C shell. Does this recursively.
- *     Note the special case: if after the piece of the curly brace is
- *     done there are no wildcard characters in the result, the result is
- *     placed on the list WITHOUT CHECKING FOR ITS EXISTENCE.  The
- *     given arguments are the entire word to expand, the first curly
- *     brace in the word, the search path, and the list to store the
- *     expansions in.
- *
- * Results:
- *     None.
- *
- * Side Effects:
- *     The given list is filled with the expansions...
- *
- *-----------------------------------------------------------------------
- */
-static void
-DirExpandCurly(const char *word, const char *brace, struct Path *path,
-    Lst *expansions)
-{
-       const char *end;        /* Character after the closing brace */
-       const char *cp;         /* Current position in brace clause */
-       const char *start;      /* Start of current piece of brace clause */
-       int bracelevel; /* Number of braces we've seen. If we see a right brace
-                        * when this is 0, we've hit the end of the clause. */
-       char *file;     /* Current expansion */
-       int otherLen;   /* The length of the other pieces of the expansion
-                        * (chars before and after the clause in 'word') */
-       char *cp2;      /* Pointer for checking for wildcards in
-                        * expansion before calling Dir_Expand */
-
-       start = brace + 1;
-
-       /*
-        * Find the end of the brace clause first, being wary of nested brace
-        * clauses.
-        */
-       for (end = start, bracelevel = 0; *end != '\0'; end++) {
-               if (*end == '{')
-                       bracelevel++;
-               else if ((*end == '}') && (bracelevel-- == 0))
-                       break;
-       }
-       if (*end == '\0') {
-               Error("Unterminated {} clause \"%s\"", start);
-               return;
-       } else
-               end++;
-
-       otherLen = brace - word + strlen(end);
-
-       for (cp = start; cp < end; cp++) {
-               /*
-                * Find the end of this piece of the clause.
-                */
-               bracelevel = 0;
-               while (*cp != ',') {
-                       if (*cp == '{')
-                               bracelevel++;
-                       else if ((*cp == '}') && (bracelevel-- <= 0))
-                               break;
-                       cp++;
-               }
-               /*
-                * Allocate room for the combination and install the
-                * three pieces.
-                */
-               file = emalloc(otherLen + cp - start + 1);
-               if (brace != word)
-                       strncpy(file, word, brace - word);
-               if (cp != start)
-                       strncpy(&file[brace - word], start, cp - start);
-               strcpy(&file[(brace - word) + (cp - start)], end);
-
-               /*
-                * See if the result has any wildcards in it. If we find one,
-                * call Dir_Expand right away, telling it to place the result
-                * on our list of expansions.
-                */
-               for (cp2 = file; *cp2 != '\0'; cp2++) {
-                       switch (*cp2) {
-                       case '*':
-                       case '?':
-                       case '{':
-                       case '[':
-                               Path_Expand(file, path, expansions);
-                               goto next;
-                       default:
-                               break;
-                       }
-               }
-               if (*cp2 == '\0') {
-                       /*
-                        * Hit the end w/o finding any wildcards, so stick
-                        * the expansion on the end of the list.
-                        */
-                       Lst_AtEnd(expansions, file);
-               } else {
-               next:
-                       free(file);
-               }
-               start = cp + 1;
-       }
-}
-
-/*-
- *-----------------------------------------------------------------------
- * DirExpandInt --
- *     Internal expand routine. Passes through the directories in the
- *     path one by one, calling DirMatchFiles for each. NOTE: This still
- *     doesn't handle patterns in directories...  Works given a word to
- *     expand, a path to look in, and a list to store expansions in.
- *
- * Results:
- *     None.
- *
- * Side Effects:
- *     Things are added to the expansions list.
- *
- *-----------------------------------------------------------------------
- */
-static void
-DirExpandInt(const char *word, const struct Path *path, Lst *expansions)
-{
-       struct PathElement *pe;
-
-       TAILQ_FOREACH(pe, path, link)
-               DirMatchFiles(word, pe->dir, expansions);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * Dir_Expand  --
- *     Expand the given word into a list of words by globbing it looking
- *     in the directories on the given search path.
- *
- * Results:
- *     A list of words consisting of the files which exist along the search
- *     path matching the given pattern is placed in expansions.
- *
- * Side Effects:
- *     Directories may be opened. Who knows?
- *-----------------------------------------------------------------------
- */
-void
-Path_Expand(char *word, struct Path *path, Lst *expansions)
-{
-       LstNode *ln;
-       char *cp;
-
-       DEBUGF(DIR, ("expanding \"%s\"...", word));
-
-       cp = strchr(word, '{');
-       if (cp != NULL)
-               DirExpandCurly(word, cp, path, expansions);
-       else {
-               cp = strchr(word, '/');
-               if (cp != NULL) {
-                       /*
-                        * The thing has a directory component -- find the
-                        * first wildcard in the string.
-                        */
-                       for (cp = word; *cp != '\0'; cp++) {
-                               if (*cp == '?' || *cp == '[' ||
-                                   *cp == '*' || *cp == '{') {
-                                       break;
-                               }
-                       }
-                       if (*cp == '{') {
-                               /*
-                                * This one will be fun.
-                                */
-                               DirExpandCurly(word, cp, path, expansions);
-                               return;
-                       } else if (*cp != '\0') {
-                               /*
-                                * Back up to the start of the component
-                                */
-                               char *dirpath;
-
-                               while (cp > word && *cp != '/')
-                                       cp--;
-                               if (cp != word) {
-                                       char sc;
-
-                                       /*
-                                        * If the glob isn't in the first
-                                        * component, try and find all the
-                                        * components up to the one with a
-                                        * wildcard.
-                                        */
-                                       sc = cp[1];
-                                       cp[1] = '\0';
-                                       dirpath = Path_FindFile(word, path);
-                                       cp[1] = sc;
-                                       /*
-                                        * dirpath is null if can't find the
-                                        * leading component
-                                        * XXX: Path_FindFile won't find internal
-                                        * components. i.e. if the path contains
-                                        * ../Etc/Object and we're looking for
-                                        * Etc, * it won't be found. Ah well.
-                                        * Probably not important.
-                                        */
-                                       if (dirpath != NULL) {
-                                               char *dp =
-                                                   &dirpath[strlen(dirpath)
-                                                   - 1];
-                                               struct Path tp =
-                                                   TAILQ_HEAD_INITIALIZER(tp);
-
-                                               if (*dp == '/')
-                                                       *dp = '\0';
-                                               Path_AddDir(&tp, dirpath);
-                                               DirExpandInt(cp + 1, &tp,
-                                                   expansions);
-                                               Path_Clear(&tp);
-                                       }
-                               } else {
-                                       /*
-                                        * Start the search from the local
-                                        * directory
-                                        */
-                                       DirExpandInt(word, path, expansions);
-                               }
-                       } else {
-                               /*
-                                * Return the file -- this should never happen.
-                                */
-                               DirExpandInt(word, path, expansions);
-                       }
-               } else {
-                       /*
-                        * First the files in dot
-                        */
-                       DirMatchFiles(word, dot, expansions);
-
-                       /*
-                        * Then the files in every other directory on the path.
-                        */
-                       DirExpandInt(word, path, expansions);
-               }
-       }
-       if (DEBUG(DIR)) {
-               LST_FOREACH(ln, expansions)
-                       DEBUGF(DIR, ("%s ", (const char *)Lst_Datum(ln)));
-               DEBUGF(DIR, ("\n"));
-       }
-}
-
-/**
- * Path_FindFile
- *     Find the file with the given name along the given search path.
- *
- * Results:
- *     The path to the file or NULL. This path is guaranteed to be in a
- *     different part of memory than name and so may be safely free'd.
- *
- * Side Effects:
- *     If the file is found in a directory which is not on the path
- *     already (either 'name' is absolute or it is a relative path
- *     [ dir1/.../dirn/file ] which exists below one of the directories
- *     already on the search path), its directory is added to the end
- *     of the path on the assumption that there will be more files in
- *     that directory later on. Sometimes this is true. Sometimes not.
- */
-char *
-Path_FindFile(char *name, struct Path *path)
-{
-       char *p1;               /* pointer into p->name */
-       char *p2;               /* pointer into name */
-       char *file;             /* the current filename to check */
-       const struct PathElement *pe;   /* current path member */
-       char *cp;               /* final component of the name */
-       bool hasSlash;  /* true if 'name' contains a / */
-       struct stat stb;        /* Buffer for stat, if necessary */
-       Hash_Entry *entry;      /* Entry for mtimes table */
-
-       /*
-        * Find the final component of the name and note whether it has a
-        * slash in it (the name, I mean)
-        */
-       cp = strrchr(name, '/');
-       if (cp != NULL) {
-               hasSlash = true;
-               cp += 1;
-       } else {
-               hasSlash = false;
-               cp = name;
-       }
-
-       DEBUGF(DIR, ("Searching for %s...", name));
-       /*
-        * No matter what, we always look for the file in the current directory
-        * before anywhere else and we *do not* add the ./ to it if it exists.
-        * This is so there are no conflicts between what the user specifies
-        * (fish.c) and what pmake finds (./fish.c).
-        */
-       if ((!hasSlash || (cp - name == 2 && *name == '.')) &&
-           (Hash_FindEntry(&dot->files, cp) != NULL)) {
-               DEBUGF(DIR, ("in '.'\n"));
-               hits += 1;
-               dot->hits += 1;
-               return (estrdup(name));
-       }
-
-       /*
-        * We look through all the directories on the path seeking one which
-        * contains the final component of the given name and whose final
-        * component(s) match the name's initial component(s). If such a beast
-        * is found, we concatenate the directory name and the final component
-        * and return the resulting string. If we don't find any such thing,
-        * we go on to phase two...
-        */
-       TAILQ_FOREACH(pe, path, link) {
-               DEBUGF(DIR, ("%s...", pe->dir->name));
-               if (Hash_FindEntry(&pe->dir->files, cp) != NULL) {
-                       DEBUGF(DIR, ("here..."));
-                       if (hasSlash) {
-                               /*
-                                * If the name had a slash, its initial
-                                * components and p's final components must
-                                * match. This is false if a mismatch is
-                                * encountered before all of the initial
-                                * components have been checked (p2 > name at
-                                * the end of the loop), or we matched only
-                                * part of one of the components of p
-                                * along with all the rest of them (*p1 != '/').
-                                */
-                               p1 = pe->dir->name + strlen(pe->dir->name) - 1;
-                               p2 = cp - 2;
-                               while (p2 >= name && p1 >= pe->dir->name &&
-                                   *p1 == *p2) {
-                                       p1 -= 1; p2 -= 1;
-                               }
-                               if (p2 >= name || (p1 >= pe->dir->name &&
-                                   *p1 != '/')) {
-                                       DEBUGF(DIR, ("component mismatch -- "
-                                           "continuing..."));
-                                       continue;
-                               }
-                       }
-                       file = str_concat(pe->dir->name, '/', cp);
-                       DEBUGF(DIR, ("returning %s\n", file));
-                       pe->dir->hits += 1;
-                       hits += 1;
-                       return (file);
-               } else if (hasSlash) {
-                       /*
-                        * If the file has a leading path component and that
-                        * component exactly matches the entire name of the
-                        * current search directory, we assume the file
-                        * doesn't exist and return NULL.
-                        */
-                       for (p1 = pe->dir->name, p2 = name; *p1 && *p1 == *p2;
-                           p1++, p2++)
-                               continue;
-                       if (*p1 == '\0' && p2 == cp - 1) {
-                               if (*cp == '\0' || ISDOT(cp) || ISDOTDOT(cp)) {
-                                       DEBUGF(DIR, ("returning %s\n", name));
-                                       return (estrdup(name));
-                               } else {
-                                       DEBUGF(DIR, ("must be here but isn't --"
-                                           " returning NULL\n"));
-                                       return (NULL);
-                               }
-                       }
-               }
-       }
-
-       /*
-        * We didn't find the file on any existing members of the directory.
-        * If the name doesn't contain a slash, that means it doesn't exist.
-        * If it *does* contain a slash, however, there is still hope: it
-        * could be in a subdirectory of one of the members of the search
-        * path. (eg. /usr/include and sys/types.h. The above search would
-        * fail to turn up types.h in /usr/include, but it *is* in
-        * /usr/include/sys/types.h) If we find such a beast, we assume there
-        * will be more (what else can we assume?) and add all but the last
-        * component of the resulting name onto the search path (at the
-        * end). This phase is only performed if the file is *not* absolute.
-        */
-       if (!hasSlash) {
-               DEBUGF(DIR, ("failed.\n"));
-               misses += 1;
-               return (NULL);
-       }
-
-       if (*name != '/') {
-               bool    checkedDot = false;
-
-               DEBUGF(DIR, ("failed. Trying subdirectories..."));
-               TAILQ_FOREACH(pe, path, link) {
-                       if (pe->dir != dot) {
-                               file = str_concat(pe->dir->name, '/', name);
-                       } else {
-                               /*
-                                * Checking in dot -- DON'T put a leading ./
-                                * on the thing.
-                                */
-                               file = estrdup(name);
-                               checkedDot = true;
-                       }
-                       DEBUGF(DIR, ("checking %s...", file));
-
-                       if (stat(file, &stb) == 0) {
-                               DEBUGF(DIR, ("got it.\n"));
-
-                               /*
-                                * We've found another directory to search. We
-                                * know there's a slash in 'file' because we put
-                                * one there. We nuke it after finding it and
-                                * call Path_AddDir to add this new directory
-                                * onto the existing search path. Once that's
-                                * done, we restore the slash and triumphantly
-                                * return the file name, knowing that should a
-                                * file in this directory every be referenced
-                                * again in such a manner, we will find it
-                                * without having to do numerous numbers of
-                                * access calls. Hurrah!
-                                */
-                               cp = strrchr(file, '/');
-                               *cp = '\0';
-                               Path_AddDir(path, file);
-                               *cp = '/';
-
-                               /*
-                                * Save the modification time so if
-                                * it's needed, we don't have to fetch it again.
-                                */
-                               DEBUGF(DIR, ("Caching %s for %s\n",
-                                   Targ_FmtTime(stb.st_mtime), file));
-                               entry = Hash_CreateEntry(&mtimes, file, NULL);
-                               Hash_SetValue(entry,
-                                   (void *)(long)stb.st_mtime);
-                               nearmisses += 1;
-                               return (file);
-                       } else {
-                               free(file);
-                       }
-               }
-
-               DEBUGF(DIR, ("failed. "));
-
-               if (checkedDot) {
-                       /*
-                        * Already checked by the given name, since . was in
-                        * the path, so no point in proceeding...
-                        */
-                       DEBUGF(DIR, ("Checked . already, returning NULL\n"));
-                       return (NULL);
-               }
-       }
-
-       /*
-        * Didn't find it that way, either. Sigh. Phase 3. Add its directory
-        * onto the search path in any case, just in case, then look for the
-        * thing in the hash table. If we find it, grand. We return a new
-        * copy of the name. Otherwise we sadly return a NULL pointer. Sigh.
-        * Note that if the directory holding the file doesn't exist, this will
-        * do an extra search of the final directory on the path. Unless
-        * something weird happens, this search won't succeed and life will
-        * be groovy.
-        *
-        * Sigh. We cannot add the directory onto the search path because
-        * of this amusing case:
-        * $(INSTALLDIR)/$(FILE): $(FILE)
-        *
-        * $(FILE) exists in $(INSTALLDIR) but not in the current one.
-        * When searching for $(FILE), we will find it in $(INSTALLDIR)
-        * b/c we added it here. This is not good...
-        */
-#ifdef notdef
-       cp[-1] = '\0';
-       Path_AddDir(path, name);
-       cp[-1] = '/';
-
-       bigmisses += 1;
-       pe = TAILQ_LAST(path, Path);
-       if (pe == NULL)
-               return (NULL);
-
-       if (Hash_FindEntry(&pe->dir->files, cp) != NULL) {
-               return (estrdup(name));
-
-       return (NULL);
-#else /* !notdef */
-       DEBUGF(DIR, ("Looking for \"%s\"...", name));
-
-       bigmisses += 1;
-       entry = Hash_FindEntry(&mtimes, name);
-       if (entry != NULL) {
-               DEBUGF(DIR, ("got it (in mtime cache)\n"));
-               return (estrdup(name));
-       } else if (stat(name, &stb) == 0) {
-               entry = Hash_CreateEntry(&mtimes, name, NULL);
-               DEBUGF(DIR, ("Caching %s for %s\n",
-                   Targ_FmtTime(stb.st_mtime), name));
-               Hash_SetValue(entry, (void *)(long)stb.st_mtime);
-               return (estrdup(name));
-       } else {
-               DEBUGF(DIR, ("failed. Returning NULL\n"));
-               return (NULL);
-       }
-#endif /* notdef */
-}
-
-/*-
- *-----------------------------------------------------------------------
- * Dir_MTime  --
- *     Find the modification time of the file described by gn along the
- *     search path dirSearchPath.
- *
- * Results:
- *     The modification time or 0 if it doesn't exist
- *
- * Side Effects:
- *     The modification time is placed in the node's mtime slot.
- *     If the node didn't have a path entry before, and Dir_FindFile
- *     found one for it, the full name is placed in the path slot.
- *-----------------------------------------------------------------------
- */
-int
-Dir_MTime(GNode *gn)
-{
-       char *fullName;         /* the full pathname of name */
-       struct stat stb;        /* buffer for finding the mod time */
-       Hash_Entry *entry;
-
-       if (gn->type & OP_ARCHV)
-               return (Arch_MTime(gn));
-
-       else if (gn->path == NULL)
-               fullName = Path_FindFile(gn->name, &dirSearchPath);
-       else
-               fullName = gn->path;
-
-       if (fullName == NULL)
-               fullName = estrdup(gn->name);
-
-       entry = Hash_FindEntry(&mtimes, fullName);
-       if (entry != NULL) {
-               /*
-                * Only do this once -- the second time folks are checking to
-                * see if the file was actually updated, so we need to
-                * actually go to the filesystem.
-                */
-               DEBUGF(DIR, ("Using cached time %s for %s\n",
-                   Targ_FmtTime((time_t)(long)Hash_GetValue(entry)),
-                   fullName));
-               stb.st_mtime = (time_t)(long)Hash_GetValue(entry);
-               Hash_DeleteEntry(&mtimes, entry);
-       } else if (stat(fullName, &stb) < 0) {
-               if (gn->type & OP_MEMBER) {
-                       if (fullName != gn->path)
-                               free(fullName);
-                       return (Arch_MemMTime(gn));
-               } else {
-                       stb.st_mtime = 0;
-               }
-       }
-       if (fullName && gn->path == NULL)
-               gn->path = fullName;
-
-       gn->mtime = stb.st_mtime;
-       return (gn->mtime);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * Path_AddDir --
- *     Add the given name to the end of the given path.
- *
- * Results:
- *     none
- *
- * Side Effects:
- *     A structure is added to the list and the directory is
- *     read and hashed.
- *-----------------------------------------------------------------------
- */
-struct Dir *
-Path_AddDir(struct Path *path, const char *name)
-{
-       Dir *d;                 /* pointer to new Path structure */
-       DIR *dir;               /* for reading directory */
-       struct PathElement *pe;
-       struct dirent *dp;      /* entry in directory */
-
-       /* check whether we know this directory */
-       TAILQ_FOREACH(d, &openDirectories, link) {
-               if (strcmp(d->name, name) == 0) {
-                       /* Found it. */
-                       if (path == NULL)
-                               return (d);
-
-                       /* Check whether its already on the path. */
-                       TAILQ_FOREACH(pe, path, link) {
-                               if (pe->dir == d)
-                                       return (d);
-                       }
-                       /* Add it to the path */
-                       d->refCount += 1;
-                       pe = emalloc(sizeof(*pe));
-                       pe->dir = d;
-                       TAILQ_INSERT_TAIL(path, pe, link);
-                       return (d);
-               }
-       }
-
-       DEBUGF(DIR, ("Caching %s...", name));
-
-       if ((dir = opendir(name)) == NULL) {
-               DEBUGF(DIR, (" cannot open\n"));
-               return (NULL);
-       }
-
-       d = emalloc(sizeof(*d));
-       d->name = estrdup(name);
-       d->hits = 0;
-       d->refCount = 1;
-       Hash_InitTable(&d->files, -1);
-
-       while ((dp = readdir(dir)) != NULL) {
-#if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define        for d_fileno */
-               /*
-                * The sun directory library doesn't check for
-                * a 0 inode (0-inode slots just take up space),
-                * so we have to do it ourselves.
-                */
-               if (dp->d_fileno == 0)
-                       continue;
-#endif /* sun && d_ino */
-
-               /* Skip the '.' and '..' entries by checking
-                * for them specifically instead of assuming
-                * readdir() reuturns them in that order when
-                * first going through a directory.  This is
-                * needed for XFS over NFS filesystems since
-                * SGI does not guarantee that these are the
-                * first two entries returned from readdir().
-                */
-               if (ISDOT(dp->d_name) || ISDOTDOT(dp->d_name))
-                       continue;
-
-               Hash_CreateEntry(&d->files, dp->d_name, NULL);
-       }
-       closedir(dir);
-
-       if (path != NULL) {
-               /* Add it to the path */
-               d->refCount += 1;
-               pe = emalloc(sizeof(*pe));
-               pe->dir = d;
-               TAILQ_INSERT_TAIL(path, pe, link);
-       }
-
-       /* Add to list of all directories */
-       TAILQ_INSERT_TAIL(&openDirectories, d, link);
-
-       DEBUGF(DIR, ("done\n"));
-
-       return (d);
-}
-
-/**
- * Path_Duplicate
- *     Duplicate a path. Ups the reference count for the directories.
- */
-void
-Path_Duplicate(struct Path *dst, const struct Path *src)
-{
-       struct PathElement *ped, *pes;
-
-       TAILQ_FOREACH(pes, src, link) {
-               ped = emalloc(sizeof(*ped));
-               ped->dir = pes->dir;
-               ped->dir->refCount++;
-               TAILQ_INSERT_TAIL(dst, ped, link);
-       }
-}
-
-/**
- * Path_MakeFlags
- *     Make a string by taking all the directories in the given search
- *     path and preceding them by the given flag. Used by the suffix
- *     module to create variables for compilers based on suffix search
- *     paths.
- *
- * Results:
- *     The string mentioned above. Note that there is no space between
- *     the given flag and each directory. The empty string is returned if
- *     Things don't go well.
- */
-char *
-Path_MakeFlags(const char *flag, const struct Path *path)
-{
-       char *str;      /* the string which will be returned */
-       char *tstr;     /* the current directory preceded by 'flag' */
-       char *nstr;
-       const struct PathElement *pe;
-
-       str = estrdup("");
-
-       TAILQ_FOREACH(pe, path, link) {
-               tstr = str_concat(flag, '\0', pe->dir->name);
-               nstr = str_concat(str, ' ', tstr);
-               free(str);
-               free(tstr);
-               str = nstr;
-       }
-
-       return (str);
-}
-
-/**
- * Path_Clear
- *
- *     Destroy a path. This decrements the reference counts of all
- *     directories of this path and, if a reference count goes 0,
- *     destroys the directory object.
- */
-void
-Path_Clear(struct Path *path)
-{
-       struct PathElement *pe;
-
-       while ((pe = TAILQ_FIRST(path)) != NULL) {
-               pe->dir->refCount--;
-               TAILQ_REMOVE(path, pe, link);
-