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