Index: share/mk/bsd.crunchgen.mk
===================================================================
--- share/mk/bsd.crunchgen.mk	(revision 240689)
+++ share/mk/bsd.crunchgen.mk	(working copy)
@@ -13,6 +13,7 @@
 #       local architecture.
 #
 # Special options can be specified for individual programs
+#  CRUNCH_OBJVAR_$(P): OBJS variable for program $(P); defaults to OBJS.${PROG}.
 #  CRUNCH_SRCDIR_$(P): base source directory for program $(P)
 #  CRUNCH_BUILDOPTS_$(P): additional build options for $(P)
 #  CRUNCH_ALIAS_$(P): additional names to be used for $(P)
@@ -49,6 +50,7 @@
 # except for those that get suppressed.
 .for D in $(CRUNCH_SRCDIRS)
 .for P in $(CRUNCH_PROGS_$(D))
+CRUNCH_OBJVAR_${P}?=	'OBJS.$${PROG}'
 .ifdef CRUNCH_SRCDIR_${P}
 $(OUTPUTS): $(CRUNCH_SRCDIR_${P})/Makefile
 .else
@@ -95,6 +97,7 @@
 .else
 	echo special $(P) buildopts DIRPRFX=${DIRPRFX}${P}/ >>$(.TARGET)
 .endif
+	echo special $(P) objvar $(CRUNCH_OBJVAR_${P}) >> $(.TARGET)
 .for A in $(CRUNCH_ALIAS_$(P))
 	echo ln $(P) $(A) >>$(.TARGET)
 .endfor
Index: share/mk/bsd.dtrace.mk
===================================================================
--- share/mk/bsd.dtrace.mk	(revision 240689)
+++ share/mk/bsd.dtrace.mk	(working copy)
@@ -42,7 +42,7 @@
 DPADD+=${LIBELF}
 LDADD+=-lelf
 
-.if defined(PROG)
+.if defined(PROG) || defined(PROGS)
 _DTRACELINKING=${OBJS}
 OBJS+=${DTRACEOBJS}
 .else
Index: share/mk/bsd.prog.mk
===================================================================
--- share/mk/bsd.prog.mk	(revision 240689)
+++ share/mk/bsd.prog.mk	(working copy)
@@ -5,222 +5,336 @@
 
 .SUFFIXES: .out .o .c .cc .cpp .cxx .C .m .y .l .ln .s .S .asm
 
-# XXX The use of COPTS in modern makefiles is discouraged.
+.if ${MK_MAN} == "no"
+NO_MAN=
+.endif
+
+# Legacy knobs
+.if defined(PROG) || defined(PROG_CXX)
+. if defined(PROG)
+PROGS=		${PROG}
+. endif
+. if defined(PROG_CXX)
+PROGS=		${PROG_CXX}
+PROGS_CXX=	${PROG_CXX}
+. endif
+# Loop once to keep pattern and avoid namespace pollution
+. for _P in ${PROGS}
+.  if defined(INTERNALPROG)
+INTERNALPROG.${_P}=
+.  endif
+.  if !defined(NO_MAN)
+.   if defined(MAN)
+MAN.${_P}=	${MAN}
+.   else
+.    for sect in 1 1aout 2 3 4 5 6 7 8 9
+.     if defined(MAN${sect})
+MAN.${_P}=	${MAN${sect}}
+.     endif
+.    endfor
+.   endif
+.  endif # defined(NO_MAN)
+.  if defined(NLSNAME) && !empty(NLSNAME)
+NLSNAME.${P}:=	${NLSNAME}
+.  endif
+.  if defined(OBJS)
+OBJS.${_P}:=	${OBJS}
+.  endif
+.  if defined(PRECIOUSPROG)
+PRECIOUSPROG.${_P}=
+.  endif
+.  if defined(PROGNAME)
+PROGNAME.${_P}=	${PROGNAME}
+.  endif
+.  if defined(SRCS)
+SRCS.${_P}:=	${SRCS}
+.  endif
+. endfor
+.else # !defined(PROG) && !defined(PROG_CXX)
+. if defined(PROGS_CXX) && !empty(PROGS_CXX)
+PROGS+=		${PROGS_CXX}
+. endif
+.endif # defined(PROG) || defined(PROG_CXX)
+
+.if defined(PROGS_CXX) && !empty(PROGS_CXX)
+. for _P in ${PROGS_CXX}
+PROG_CXX.${_P}=
+. endfor
+.endif
+
+# Avoid recursive variables
+.undef NLSNAME
+
 .if defined(COPTS)
 CFLAGS+=${COPTS}
 .endif
 
+.if defined(DEBUG_FLAGS)
+. if ${MK_CTF} != "no" && ${DEBUG_FLAGS:M-g} != ""
+CTFFLAGS+= -g
+. endif
+CFLAGS+=${DEBUG_FLAGS}
+CXXFLAGS+=${DEBUG_FLAGS}
+.endif
+
+STRIP?=		-s
+
 .if ${MK_ASSERT_DEBUG} == "no"
 CFLAGS+= -DNDEBUG
 NO_WERROR=
 .endif
 
-.if defined(DEBUG_FLAGS)
-CFLAGS+=${DEBUG_FLAGS}
-CXXFLAGS+=${DEBUG_FLAGS}
+.for _P in ${PROGS}
 
-.if ${MK_CTF} != "no" && ${DEBUG_FLAGS:M-g} != ""
-CTFFLAGS+= -g
-.endif
-.endif
+BINDIR.${_P}?=	${BINDIR}
+BINGRP.${_P}?=	${BINGRP}
+BINMODE.${_P}?=	${BINMODE}
+BINOWN.${_P}?=	${BINOWN}
 
-.if defined(CRUNCH_CFLAGS)
-CFLAGS+=${CRUNCH_CFLAGS}
-.endif
+CFLAGS.${_P}+=	${CFLAGS}
+CXXFLAGS.${_P}+= ${CXXFLAGS}
+DPADD.${_P}+=	${DPADD}
+LDADD.${_P}+=	${LDADD}
+LDFLAGS.${_P}+=	${LDFLAGS}
 
-.if !defined(DEBUG_FLAGS)
-STRIP?=	-s
-.endif
+INSTALLFLAGS.${_P}?= ${INSTALLFLAGS}
 
-.if defined(NO_SHARED) && (${NO_SHARED} != "no" && ${NO_SHARED} != "NO")
-LDFLAGS+= -static
-.endif
+. if defined(PRECIOUSPROG.${_P})
+.  if !defined(NO_FSCHG) && !defined(NO_FSCHG.${_P})
+INSTALLFLAGS.${_P}+= -fschg
+.  endif
+INSTALLFLAGS.${_P}+= -S
+. endif
 
-.if defined(PROG_CXX)
-PROG=	${PROG_CXX}
-.endif
+NO_SHARED.${_P}?=	${NO_SHARED}
 
-.if defined(PROG)
-.if defined(SRCS)
+. if !defined(NLSDIR.${_P})
+NLSDIR.${_P}:=	${NLSDIR}
+. endif
+. undef NLSDIR
 
-OBJS+=  ${SRCS:N*.h:R:S/$/.o/g}
+. if !empty(NO_SHARED.${_P}) && ${NO_SHARED.${_P}:tl} != "no"
+LDFLAGS.${_P}+= -static
+. endif
 
-.if target(beforelinking)
-${PROG}: ${OBJS} beforelinking
-.else
-${PROG}: ${OBJS}
-.endif
-.if defined(PROG_CXX)
-	${CXX} ${CXXFLAGS} ${LDFLAGS} -o ${.TARGET} ${OBJS} ${LDADD}
-.else
-	${CC} ${CFLAGS} ${LDFLAGS} -o ${.TARGET} ${OBJS} ${LDADD}
-.endif
-.if ${MK_CTF} != "no"
-	${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${OBJS}
-.endif
+. if defined(SRCS.${_P})
 
-.else	# !defined(SRCS)
+_SRCS:=		${SRCS.${_P}}
+OBJS.${_P}+=	${_SRCS:N*.h:R:S/$/.o/g}
 
-.if !target(${PROG})
-.if defined(PROG_CXX)
-SRCS=	${PROG}.cc
-.else
-SRCS=	${PROG}.c
-.endif
+.  if target(beforelinking)
+${_P}: ${OBJS.${_P}} beforelinking
+.  else
+${_P}: ${OBJS.${_P}}
+.  endif
+.  if defined(PROG_CXX.${_P})
+	${CXX} ${CXXFLAGS.${_P}} ${LDFLAGS.${_P}} -o ${.TARGET} ${OBJS.${_P}} \
+	    ${LDADD.${_P}}
+.  else
+	${CC} ${CFLAGS.${_P}} ${LDFLAGS.${_P}} -o ${.TARGET} ${OBJS.${_P}} \
+	    ${LDADD.${_P}}
+.  endif
+.  if ${MK_CTF} != "no"
+	${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${OBJS.${_P}}
+.  endif
 
+. else # !defined(SRCS.${_P})
+
+.  if !target(${_P})
+.   if defined(PROG_CXX.${_P})
+SRCS.${_P}?=	${_P}.cc
+.   else
+SRCS.${_P}?=	${_P}.c
+.   endif
+
 # Always make an intermediate object file because:
 # - it saves time rebuilding when only the library has changed
 # - the name of the object gets put into the executable symbol table instead of
 #   the name of a variable temporary object.
 # - it's useful to keep objects around for crunching.
-OBJS=	${PROG}.o
+OBJS.${_P}:=	${_P}.o
 
-.if target(beforelinking)
-${PROG}: ${OBJS} beforelinking
-.else
-${PROG}: ${OBJS}
-.endif
-.if defined(PROG_CXX)
-	${CXX} ${CXXFLAGS} ${LDFLAGS} -o ${.TARGET} ${OBJS} ${LDADD}
-.else
-	${CC} ${CFLAGS} ${LDFLAGS} -o ${.TARGET} ${OBJS} ${LDADD}
-.endif
-.if ${MK_CTF} != "no"
-	${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${OBJS}
-.endif
-.endif
+.   if target(beforelinking)
+${_P}: ${OBJS.${_P}} beforelinking
+.   else
+${_P}: ${OBJS.${_P}}
+.   endif # target(beforelinking)
+.   if defined(PROG_CXX.${_P})
+	${CXX} ${CXXFLAGS.${_P}} ${LDFLAGS.${_P}} -o ${.TARGET} ${OBJS.${_P}} \
+	    ${LDADD.${_P}}
+.   else
+	${CC} ${CFLAGS.${_P}} ${LDFLAGS.${_P}} -o ${.TARGET} ${OBJS.${_P}} \
+	    ${LDADD.${_P}}
+.   endif
+.   if ${MK_CTF} != "no"
+	${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${OBJS.${_P}}
+.   endif
 
-.endif
+.  endif # !target(${_P})
 
-.if	${MK_MAN} != "no" && !defined(MAN) && \
-	!defined(MAN1) && !defined(MAN2) && !defined(MAN3) && \
-	!defined(MAN4) && !defined(MAN5) && !defined(MAN6) && \
-	!defined(MAN7) && !defined(MAN8) && !defined(MAN9) && \
-	!defined(MAN1aout)
-MAN=	${PROG}.1
-MAN1=	${MAN}
-.endif
-.endif
+. endif # defined(SRCS.${_P})
 
-all: objwarn ${PROG} ${SCRIPTS}
-.if ${MK_MAN} != "no"
+CLEANFILES+= 	${OBJS.${_P}}
+
+.endfor # for _P in ${PROGS}
+
+all: objwarn ${PROGS} ${SCRIPTS}
+
+.if !defined(NO_MAN)
+. for _P in ${PROGS}
+MAN.${_P}?=	${_P}.1
+MAN:=		${MAN.${_P}}
+.  include <bsd.man.mk>
+. endfor
+. if target(_manpages) # bsd.man.mk was included
 all: _manpages
+. endif
 .endif
 
-.if defined(PROG)
-CLEANFILES+= ${PROG}
-.endif
+CLEANFILES+=	${PROGS}
 
-.if defined(OBJS)
-CLEANFILES+= ${OBJS}
-.endif
-
 .include <bsd.libnames.mk>
 
-.if defined(PROG)
 _EXTRADEPEND:
-.if defined(LDFLAGS) && !empty(LDFLAGS:M-nostdlib)
-.if defined(DPADD) && !empty(DPADD)
-	echo ${PROG}: ${DPADD} >> ${DEPENDFILE}
-.endif
-.else
-	echo ${PROG}: ${LIBC} ${DPADD} >> ${DEPENDFILE}
-.if defined(PROG_CXX)
-.if !empty(CXXFLAGS:M-stdlib=libc++)
-	echo ${PROG}: ${LIBCPLUSPLUS} >> ${DEPENDFILE}
-.else
-	echo ${PROG}: ${LIBSTDCPLUSPLUS} >> ${DEPENDFILE}
-.endif
-.endif
-.endif
-.endif
+.for _P in ${PROGS}
+. if !empty(LDFLAGS.${P}:M-nostdlib)
+.  if !empty(DPADD.${_P})
+	echo ${_P}: ${DPADD.${_P}} >> ${DEPENDFILE}
+.  endif
+. else
+	echo ${_P}: ${LIBC} ${DPADD.${_P}} >> ${DEPENDFILE}
+.  if defined(PROG_CXX.${_P})
+.   if !empty(CXXFLAGS.${P}:M-stdlib=libc++)
+	echo ${_P}: ${LIBCPLUSPLUS} >> ${DEPENDFILE}
+.   else
+	echo ${_P}: ${LIBSTDCPLUSPLUS} >> ${DEPENDFILE}
+.   endif
+.  endif
+. endif
+.endfor
 
 .if !target(install)
 
-.if defined(PRECIOUSPROG)
-.if !defined(NO_FSCHG)
-INSTALLFLAGS+= -fschg
-.endif
-INSTALLFLAGS+= -S
-.endif
+. if !target(realinstall)
 
-_INSTALLFLAGS:=	${INSTALLFLAGS}
-.for ie in ${INSTALLFLAGS_EDIT}
-_INSTALLFLAGS:=	${_INSTALLFLAGS${ie}}
-.endfor
+.  for _P in ${PROGS}
 
-.if !target(realinstall) && !defined(INTERNALPROG)
-realinstall: _proginstall
-.ORDER: beforeinstall _proginstall
-_proginstall:
-.if defined(PROG)
-.if defined(PROGNAME)
-	${INSTALL} ${STRIP} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
-	    ${_INSTALLFLAGS} ${PROG} ${DESTDIR}${BINDIR}/${PROGNAME}
-.else
-	${INSTALL} ${STRIP} -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
-	    ${_INSTALLFLAGS} ${PROG} ${DESTDIR}${BINDIR}
-.endif
-.endif
-.endif	# !target(realinstall)
+.   if !defined(INTERNALPROG.${_P})
 
-.if defined(SCRIPTS) && !empty(SCRIPTS)
-realinstall: _scriptsinstall
-.ORDER: beforeinstall _scriptsinstall
+.ORDER: beforeinstall _proginstall.${_P}
+_proginstall.${_P}:
+.    if defined(PROGNAME.${_P})
+	${INSTALL} ${STRIP} -o ${BINOWN.${_P}} -g ${BINGRP.${_P}} \
+	    -m ${BINMODE.${_P}} ${INSTALLFLAGS.${_P}} ${_P} \
+	    ${DESTDIR}${BINDIR.${_P}}/${PROGNAME.${_P}}
+.    else
+	${INSTALL} ${STRIP} -o ${BINOWN.${_P}} -g ${BINGRP.${_P}} \
+	    -m ${BINMODE.${_P}} ${INSTALLFLAGS.${_P}} ${_P} \
+	    ${DESTDIR}${BINDIR.${_P}}
+.    endif 
 
+realinstall: _proginstall.${_P}
+
+.   endif # !defined(INTERNALPROG.${_P})
+
+.  endfor # for _P in ${PROGS}
+
+. endif # !target(realinstall)
+
+. if defined(SCRIPTS) && !empty(SCRIPTS)
 SCRIPTSDIR?=	${BINDIR}
 SCRIPTSOWN?=	${BINOWN}
 SCRIPTSGRP?=	${BINGRP}
 SCRIPTSMODE?=	${BINMODE}
 
-.for script in ${SCRIPTS}
-.if defined(SCRIPTSNAME)
-SCRIPTSNAME_${script:T}?=	${SCRIPTSNAME}
-.else
-SCRIPTSNAME_${script:T}?=	${script:T:R}
-.endif
-SCRIPTSDIR_${script:T}?=	${SCRIPTSDIR}
-SCRIPTSOWN_${script:T}?=	${SCRIPTSOWN}
-SCRIPTSGRP_${script:T}?=	${SCRIPTSGRP}
-SCRIPTSMODE_${script:T}?=	${SCRIPTSMODE}
-_scriptsinstall: _SCRIPTSINS_${script:T}
-_SCRIPTSINS_${script:T}: ${script}
-	${INSTALL} -o ${SCRIPTSOWN_${.ALLSRC:T}} \
-	    -g ${SCRIPTSGRP_${.ALLSRC:T}} -m ${SCRIPTSMODE_${.ALLSRC:T}} \
+.  for S in ${SCRIPTS}
+
+realinstall: scriptsinstall
+.ORDER: beforeinstall scriptsinstall
+
+.   if defined(SCRIPTSNAME)
+SCRIPTSNAME_${S}?= ${SCRIPTSNAME}
+.   else
+SCRIPTSNAME_${S}?= ${S:T:R}
+.   endif
+
+SCRIPTSDIR_${S}?= ${SCRIPTSDIR}
+SCRIPTSOWN_${S}?= ${SCRIPTSOWN}
+SCRIPTSGRP_${S}?= ${SCRIPTSGRP}
+SCRIPTSMODE_${S}?= ${SCRIPTSMODE}
+
+scriptsinstall: ${DESTDIR}${SCRIPTSDIR_${S}}/${SCRIPTSNAME_${S}}
+
+${DESTDIR}${SCRIPTSDIR_${S}}/${SCRIPTSNAME_${S}}: ${S}
+	${INSTALL} -o ${SCRIPTSOWN_${S}} \
+	    -g ${SCRIPTSGRP_${S}} \
+	    -m ${SCRIPTSMODE_${S}} \
 	    ${.ALLSRC} \
-	    ${DESTDIR}${SCRIPTSDIR_${.ALLSRC:T}}/${SCRIPTSNAME_${.ALLSRC:T}}
-.endfor
+	    ${.TARGET}
+
+.  endfor # for S in ${SCRIPTS}
+
+. endif # defined(SCRIPTS) && !empty(SCRIPTS)
+
+.endif # !target(install)
+
+.if !defined(NO_MAN)
+. if target(_manpages) # bsd.man.mk was included
+realinstall: _maninstall
+. endif
 .endif
 
-NLSNAME?=	${PROG}
+# Wrap bsd.nls.mk because I can't force that Makefile snippet to work only with
+# ${PROGS}.
+.for _P in ${PROGS}
+NLSNAME.${_P}?=	${_P}
+NLS:=		${NLS.${_P}}
+NLSDIR:=	${NLSDIR.${_P}}
+NLSNAME:=	${NLSNAME.${_P}}
 .include <bsd.nls.mk>
+.endfor
 
 .include <bsd.files.mk>
 .include <bsd.incs.mk>
 .include <bsd.links.mk>
 
-.if ${MK_MAN} != "no"
-realinstall: _maninstall
-.ORDER: beforeinstall _maninstall
-.endif
+.if !target(lint)
+. for _P in ${PROGS}
+.  if !target(lint.${_P})
+.   if defined(PROG_CXX.${_P})
+lint.${_P}:
+.   else
+_CFLAGS:=	${CFLAGS.${_P}}
+_SRCS:=		${SRCS.${_P}}
+lint.${_P}: ${_SRCS:M*.c}
+	${LINT} ${LINTFLAGS} ${_CFLAGS:M-[DIU]*} ${.ALLSRC}
+.   endif
+.  endif
+lint: lint.${_P}
 
-.endif
+. endfor
+.endif # !target(lint)
 
-.if !target(lint)
-lint: ${SRCS:M*.c}
-.if defined(PROG)
-	${LINT} ${LINTFLAGS} ${CFLAGS:M-[DIU]*} ${.ALLSRC}
-.endif
-.endif
+.for _P in ${PROGS}
+CFLAGS:=	${CFLAGS.${_P}}
+CXXFLAGS:=	${CXXFLAGS.${_P}}
+SRCS:=		${SRCS.${_P}}
+. include <bsd.dep.mk>
+# bsd.dep.mk mangles SRCS
+SRCS.${_P}:=	${SRCS}
+.endfor
 
-.if ${MK_MAN} != "no"
-.include <bsd.man.mk>
+# XXX: emulate the old bsd.prog.mk by allowing Makefiles that didn't set
+# ${PROG*} to function with this Makefile snippet.
+.if empty(PROGS)
+. include <bsd.dep.mk>
 .endif
 
-.include <bsd.dep.mk>
-
-.if defined(PROG) && !exists(${.OBJDIR}/${DEPENDFILE})
-${OBJS}: ${SRCS:M*.h}
+.if !exists(${.OBJDIR}/${DEPENDFILE})
+. for _P in ${PROGS}
+_SRCS:=		${SRCS.${_P}}
+${OBJS.${_P}}: ${_SRCS:M*.h}
+. endfor
 .endif
 
 .include <bsd.obj.mk>
Index: share/mk/bsd.README
===================================================================
--- share/mk/bsd.README	(revision 240689)
+++ share/mk/bsd.README	(working copy)
@@ -207,98 +207,157 @@
 
 It sets/uses the following variables:
 
-BINGRP		Binary group.
+Variables global to all programs:
 
-BINOWN		Binary owner.
+CLEANFILES		Additional files to remove and
+CLEANDIRS		additional directories to remove during clean and cleandir
+			targets.  "rm -f" and "rm -rf" used respectively.
 
-BINMODE		Binary mode.
+DEBUG_FLAGS		debugging specific CFLAGS/LDFLAGS; if set any binaries
+ 			produced will not be stripped.  See also: WITH_CTF
 
-CLEANFILES	Additional files to remove and
-CLEANDIRS	additional directories to remove during clean and cleandir
-		targets.  "rm -f" and "rm -rf" used respectively.
+FILES			A list of non-executable files.
+			The installation is controlled by the FILESNAME, FILESOWN,
+			FILESGRP, FILESMODE, FILESDIR variables that can be
+			further specialized by FILES<VAR>_<file>.
 
-CFLAGS		Flags to the compiler when creating C objects.
+LINKS			The list of binary links; should be full pathnames, the
+			linked-to file coming first, followed by the linked
+			file.  The files are hard-linked.  For example, to link
+			/bin/test and /bin/[, use:
 
-FILES		A list of non-executable files.
-		The installation is controlled by the FILESNAME, FILESOWN,
-		FILESGRP, FILESMODE, FILESDIR variables that can be
-		further specialized by FILES<VAR>_<file>.
+			LINKS=	${DESTDIR}/bin/test ${DESTDIR}/bin/[
 
-LDADD		Additional loader objects.  Usually used for libraries.
-		For example, to load with the compatibility and utility
-		libraries, use:
+PROG			The name of the program to build.  If not supplied,
+			nothing is built.
 
+PROG_CXX		If defined, the name of the C++ program to build.  Also
+			causes <bsd.prog.mk> to link the program with the
+			standard C++ library.  PROG_CXX overrides the value
+			of PROG if PROG is also set.
+
+STRIP			The flag passed to the install program to cause the
+			binary to be stripped.  This is to be used when
+			building your own install script so that the entire
+			system can be made stripped/not-stripped using a
+			single knob.
+
+SUBDIR			A list of subdirectories that should be built as well.
+			Each of the targets will execute the same target in the
+			subdirectories.
+
+The following variables can be tuned for specific program use (you will need
+to suffix variable declarations with .${PROG}, e.g. PROG= foo -> SRCS.foo):
+
+BINDIR			Binary directory.
+
+BINGRP			Binary group.
+
+BINOWN			Binary owner.
+
+BINMODE			Binary mode.
+
+CFLAGS			Flags to the compiler when creating C objects.
+
+DPADD			Additional dependencies for the program.  Usually used
+			for libraries.  For example, to depend on the
+			compatibility and utility libraries use:
+
+				DPADD=${LIBCOMPAT} ${LIBUTIL}
+
+			There is a predefined identifier for each
+			(non-profiled, non-shared) library and object.  Library
+			file names are transformed to identifiers by removing
+			the extension and converting to upper case.
+
+			There are no special identifiers for profiled or shared
+			libraries or objects.  The identifiers for the standard
+			libraries are used in DPADD.  This works correctly iff
+			all the libraries are built at the same time.
+			Unfortunately, it causes unnecessary relinks to shared
+			libraries when only the static libraries have changed.
+			Dependencies on shared libraries should be only on the
+			library version numbers.
+
+INSTALLFLAGS		install(1) flags.
+
+LDADD			Additional loader objects.  Usually used for libraries.
+			For example, to load with the compatibility and utility
+			libraries, use:
+
 			LDADD=-lutil -lcompat
 
-LDFLAGS		Additional loader flags.
+LDFLAGS			Additional loader flags.
 
-LINKS		The list of binary links; should be full pathnames, the
-		linked-to file coming first, followed by the linked
-		file.  The files are hard-linked.  For example, to link
-		/bin/test and /bin/[, use:
+MAN			Manual pages (should end in .1 - .9).  If no MAN
+			variable is defined, "MAN=<PROG>.1" is assumed.
 
-			LINKS=	${DESTDIR}/bin/test ${DESTDIR}/bin/[
+NO_FSCHG		Do not call install(1) with -f schg.
 
-MAN		Manual pages (should end in .1 - .9).  If no MAN variable
-		is defined, "MAN=${PROG}.1" is assumed.
+PRECIOUSPROG		Install with -S (safe copy) and handle NO_FSCHG
+			variable case as well.
 
-PROG		The name of the program to build.  If not supplied, nothing
-		is built.
+PROG_CXX		C++ application name(s); the sources for the
+			application(s) are compiled via ${CXX}
 
-PROG_CXX	If defined, the name of the program to build.  Also
-		causes <bsd.prog.mk> to link the program with the
-		standard C++ library.  PROG_CXX overrides the value
-		of PROG if PROG is also set.
+PROGNAME		The name that the above program will be installed, if
+			different from <PROG>.
 
-PROGNAME	The name that the above program will be installed as, if
-		different from ${PROG}.
+SRCS			List of source files to build the program.  If SRCS is
+			not defined, it's assumed to be ${PROG}.c or, if
+			PROG_CXX is defined, ${PROG_CXX}.cc.
 
-SRCS		List of source files to build the program.  If SRCS is not
-		defined, it's assumed to be ${PROG}.c or, if PROG_CXX is
-		defined, ${PROG_CXX}.cc.
+SCRIPTS			A list of interpreter scripts [file.{sh,csh,pl,awk,...}].
+			The installation is controlled by the SCRIPTSNAME, SCRIPTSOWN,
+			SCRIPTSGRP, SCRIPTSMODE, SCRIPTSDIR variables that can be
+			further specialized by SCRIPTS<VAR>_<script>.
 
-DPADD		Additional dependencies for the program.  Usually used for
-		libraries.  For example, to depend on the compatibility and
-		utility libraries use:
+The following variables can be tuned for specific scripts; you will need
+to suffix variable declarations with _<SCRIPT>, e.g.
+SCRIPT -> foo, -> SCRIPTDIR_foo.  In all cases, the per-script variables
+default to the equivalent global SCRIPT* variable and fallback to the
+BIN* equivalents, e.g. SCRIPTDIR_foo falls back to SCRIPTDIR if SCRIPTDIR_foo
+is not defined, then BINDIR if SCRIPTDIR is not defined:
 
-			DPADD=${LIBCOMPAT} ${LIBUTIL}
+SCRIPTSDIR		Directory to install a script to.
 
-		There is a predefined identifier for each (non-profiled,
-		non-shared) library and object.  Library file names are
-		transformed to identifiers by removing the extension and
-		converting to upper case.
+SCRIPTGRP		Group to set for a script.
 
-		There are no special identifiers for profiled or shared
-		libraries or objects.  The identifiers for the standard
-		libraries are used in DPADD.  This works correctly iff all
-		the libraries are built at the same time.  Unfortunately,
-		it causes unnecessary relinks to shared libraries when
-		only the static libraries have changed.  Dependencies on
-		shared libraries should be only on the library version
-		numbers.
+SCRIPTMODE		Mode to apply to a script.
 
-STRIP		The flag passed to the install program to cause the binary
-		to be stripped.  This is to be used when building your
-		own install script so that the entire system can be made
-		stripped/not-stripped using a single nob.
+SCRIPTOWN		Owner to set for a script.
 
-SUBDIR		A list of subdirectories that should be built as well.
-		Each of the targets will execute the same target in the
-		subdirectories.
+Legacy variables are as follows:
 
-SCRIPTS		A list of interpreter scripts [file.{sh,csh,pl,awk,...}].
-		The installation is controlled by the SCRIPTSNAME, SCRIPTSOWN,
-		SCRIPTSGRP, SCRIPTSMODE, SCRIPTSDIR variables that can be
-		further specialized by SCRIPTS<VAR>_<script>.
+COPTS			Optimization flags appended to CFLAGS; highly
+ 			discouraged in modern Makefiles.
 
+PROG			Legacy form of `PROGS`
+
+PROG_CXX		Legacy form of `PROGS_CXX`
+
+The following variables are wrapped to be made `PROGS aware`:
+
+NLS			See bsd.nls.mk description for more details.
+NLSDIR
+NLSNAME
+
+Developer convenience variables:
+
+WITH_ASSERT_DEBUG	Compile with CFLAGS+=-DNDEBUG
+
 The include file <bsd.prog.mk> includes the file named "../Makefile.inc"
-if it exists, as well as the include file <bsd.man.mk>.
+if it exists, as well as the include file <bsd.man.mk>.  Furthermore, if
+WITH_NLS is defined and NLS.<PROG> is also defined, then bsd.nls.mk is
+included as well.
 
 Some simple examples:
 
+1. Single C Program:
+
 To build foo from foo.c with a manual page foo.1, use:
 
-	PROG=	foo
+	PROGS=	foo
 
 	.include <bsd.prog.mk>
 
@@ -314,6 +373,34 @@
 
 	SRCS=	a.c b.c c.c d.c
 
+2. Single C++ Program:
+
+To build bar with bar.cc with a manual page bar.1, use:
+
+	PROGS_CXX=	bar
+
+	.include <bsd.prog.mk>
+
+All other constructs are the same as in the Single C Program case.
+
+3. Multiple C programs:
+
+To build foo from foo.c and bar with bar.c, use:
+
+	PROGS=	foo bar
+
+	.include <bsd.prog.mk>
+
+To build foo from bar.c and bar with foo.c, use:
+
+	PROGS=	foo bar
+
+	SRCS.foo= bar.c
+
+	SRCS.bar= foo.c
+
+	.include <bsd.prog.mk>
+
 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 
 The include file <bsd.subdir.mk> contains the default targets for building
