From: Tom Christiansen <tchrist@convex.COM>
Subject: Re: Is anyone using m4?
Originator: tchrist@pixel.convex.com
Date: Tue, 10 Nov 1992 16:47:18 GMT
Distribution: comp.*.unix
Reply-To: tchrist@convex.COM (Tom Christiansen)
Organization: Convex Computer Corporation, Colorado Springs, CO
Keywords: m4,macro,preprocessor
X-Disclaimer: This message was written by a user at CONVEX Computer
              Corp. The opinions expressed are those of the user and
              not necessarily those of CONVEX.

From the keyboard of boyd@prl.dec.com (Boyd Roberts):
:Yeah, we use it to generate N window manager rc's from a set
:of standard configs that all of them include.  m4 is cool.

m4 is so amazingly cool that before perl, it used to be my
favorite unix tool. :-)

consider the following m4 program, which generates a syslog.conf
file with all kinds of conditionals, like 4.2 vs 4.3, strange
LOG_ entries derived from #include files, expanding the operations alias
for biffing, and knowing what machines belong to what admin domain
it's in so we know about sending to the right loghost.  First, 
the thing that makes the machine definitions:

    define(`TMP',maketemp(/tmp/syslog.XXXXX))dnl
    changequote([,])dnl
    syscmd([hostname | sed 's/.*/define(`'"HOST'"',`'"&'"')dnl/'] > TMP)dnl
    changequote(`,')dnl
    include(TMP)dnl
    changequote(^A,^B)dnl
    syscmd(^A(echo 'r /usr/adm/MACHINES';
	      echo '%s/[    ][a-zA-Z0-9_]*\>/\U&/g';
	      echo '%p';
	      echo 'q!') | ex - - | tr -d '\015' | awk '$1 == "^BHOST^A" { 
		for (i=2;i<NF;i++) 
		    if ($i && $i != ".") {
			pos = index($i,"=");
			if (pos) { 
			    printf "define(%c%s%c,%c%s%c)dnl\n", \
				96, substr($i,1,pos-1), 39,\
				96, substr($i,pos+1,length($i)-pos), 39; 
			} else {
			    printf "define(%c%s%c)dnl\n", 96, $i, 39;
			}
		    }}'^B > TMP)dnl
    changequote(`,')dnl
    include(TMP)dnl
    syscmd(rm TMP)dnl
    ifdef(`MIS',    `define(`ADMIN',`mis')define(`LOGHOST',`convex')')dnl
    ifdef(`MKTG',   `define(`ADMIN',`mktg')define(`LOGHOST',`convex1')')dnl
    ifdef(`TAC',    `define(`ADMIN',`tac')define(`LOGHOST',`sushi')')dnl
    ifdef(`C1',`define(CONVEX)')dnl
    ifdef(`C2',`define(CONVEX)')dnl
    ifdef(`C3',`define(CONVEX)')dnl
    ifdef(`LOGHOST',,`ifdef(`DOALLPASSWD',`define(`ADMIN',`engr')define(`LOGHOST',`c
    oncave')')')dnl
    ifelse(LOGHOST,HOST,`undefine(`LOGHOST')')dnl

now the syslog.conf.global file itself, which uses the preceding one:

    #
    changequote({,})dnl
    ifdef(impossible_thing,{#
    # global syslog configuration file.
    #
    # This file is processed by m4 so be careful to quote (`') names
    # that match m4 reserved words.  Also, within ifdef's, arguments
    # containing commas must be quoted.  This hackery crafted by
    # tchrist.
    #
    # Note: The interpretation given within to `LOGHOST' is opposite
    # what sun does.  That is, if it is defined, it is the name of the 
    # host who collects syslog information for this administrative domain.
    # We still log locally as well in case of network snafus.
    },{dnl
    # This is the local syslog.conf file; it has been generated 
    # automatically using "m4 < syslog.conf.global > syslog.conf",
    # and therefore should never be edited by hand.  It has included
    # syslog.conf.local if this file existed.
    #
    # Note: Have to exclude user from most lines so that user.alert
    #	and user.emerg are not included, because old sendmails
    #	will generate them for debugging information.  If you
    #	have no 4.2BSD based systems doing network logging, you
    #	can remove all the special cases for "user" logging.
    #
    })dnl
    changequote(`,')dnl
    include(`/usr/adm/etc/stddefs.m4')dnl
    changequote({,})dnl
    syscmd({sed -n -e 's/^[ 	]*#define[ 	][ 	]*\(LOG_[A-Z0-9]*\)[ 	].*/define(`\1'"')dnl/p" < /usr/include/syslog.h} > TMP)dnl
    changequote(`,')dnl
    include(TMP)dnl
    ifdef(`LOG_DAEMON',
    `
    # critical and authorization stuff gets wide notice
    #
    *.warn;user,kern.none			/usr/adm/log/critical
    *.warn;kern,user.none;auth.info		/dev/console'
    ifdef(`LOGHOST',`
    `
    # forward noteworthy stuff to 'LOGHOST`, our administrative domain master
    #'
    *.warn;kern`,'auth.info;local7.none	@LOGHOST
    ')dnl
    `
    *.warn;user,kern.none	kuryla,root

    kern.debug				/usr/adm/log/kernlog
    auth.debug				/usr/adm/log/authlog
    daemon.debug				/usr/adm/log/daemonlog
    lpr.debug				/usr/adm/log/lpd-errs
    mail.debug				/usr/spool/mqueue/syslog
    syslog.debug				/usr/adm/log/syslog
    user.debug				/usr/adm/log/messages'

    `# next entries do not always exist on all old-style systems
    #'
    ifdef(`LOG_BATCH',`batch.info				/usr/adm/log/batchlog
    ')dnl
    ifdef(`LOG_CRON',`cron.info				/usr/adm/log/cronlog
    ')dnl
    ifdef(`LOG_NEWS',`news.info				/usr/adm/log/newslog
    #ifelse(`concave',HOST,,``#' to track new notes locking for tchrist
    #news.debug				@concave')
    #')dnl
    ifdef(`LOG_TAPE',`tape.debug				/usr/adm/log/tapelog
    ')dnl
    `# local0 is errlogd, local7 come from the cisco routers
    #
    local0.debug				/usr/adm/log/errlog
    local1.debug                            /usr/adm/log/monitorlog
    local3.debug				@mikey
    local7.debug				/usr/adm/log/ciscolog
    #
    # END OF /etc/syslog.conf.global
    # local stuff follows and comes from syslog.conf.local'
    sinclude(`/etc/syslog.conf.local')dnl
    ,# old style syslog
    9/usr/spool/mqueue/syslog
    7/usr/adm/log/critical
    5/dev/console

    changequote({,})dnl
    syscmd({/usr/lib/sendmail -bv operations | sed -e 's/.*!//' -e 's/\..*//'} > TMP)dnl
    include(TMP)root
    )dnl
    syscmd(rm TMP)dnl


aren't you glad i use perl now? :-)

--tom
-- 
    Tom Christiansen      tchrist@convex.com      convex!tchrist

Time flies like an arrow
Fruit flies like a banana
Xref: sparky comp.unix.misc:4118 comp.unix.questions:13267 comp.sys.sgi:16321 comp.graphics:11779