2026-01-04 - M1 Macro Processor Retreat
=======================================
I wrote a prototype gopher front-end to the Internet Archive. It was
a single file AWK script using CGI. In some ways it was elegant, but
i received feedback that it should be broken into smaller files.
PHAROS
GNU AWK has an include() function, but i wasn't using gawk. So i
implemented include() using m4, which will work with any AWK. I
wrote macros portable to both BSD and GNU m4. It seemed like a
reasonable combination because AWK and m4 are both part of POSIX.
Macro processors have been called a rite of passage for programmers
since the beginning of time. I've spent a lot of time debugging
GNU autoconf scripts. Don't get me started on automake and libtool.
The proliferation of new build systems takes it way past
"rite of passage" material. Now it's more like a gauntlet. In
contrast, imake and xmkmf look like child's play.
Child's play is what i like about minimal software. Toys are fun.
Code i can wrap my mind around in a single lazy Sunday afternoon. So
i was delighted to discover another antique: the m1 macro processor.
If m4 is the advanced stage, then m1 isn't even larval yet. m1 is
more of a retreat than a rite of passage.
What a coincidence, the author used m1 to create a module system for
AWK, just as i had done with m4! m1 was written in just a little
over 100 lines of AWK code. I found a version extended by
Dave Bucklin to support RPN math expressions.
m1.awk
M1 article
Just for fun i wrote expr.m1, a small macro to do infix math
expressions. I didn't need to change m1.awk. Behind the scenes it
uses the @shell macro to evaluate each expression through an AWK
child process.
expr.m1
Here is an example:
$ cat >test1.txt <<__EOF__
@include expr.m1
@define cols 24
@define rows 80
@expr@ cells @(@ @cols@ * @rows@ @)@
Cells = @cells@
__EOF__
$ awk -f m1.awk test1.txt
Cells = 1920
While reading about macro processors, i found ML/I. It can often
transform its own source code to a host assembler or compiler. I
imagine it's possible to implement m1 using ML/I, but i suspect it
would take two passes. Scanning the documentation i don't see how
ML/I could implement the @include macro without a helper program.
ML/I
Bailing wire and duct tape are classics; they never get old. :)
See also:
Using the m4 macro processor for fun and profit
Exploiting the m4 macro language by Kenneth J. Turner (PDF)
M4 complete guide by Jerry Peek
M4 quoting tips
Notes on the M4 Macro Language by Michael Breen
tags: retrocomputing,technical
Tags
====
retrocomputing
technical