M4 — a blast from the past

This week (2014 01 05), I redesigned all my webpages. I spent last week reading "CSS3: The Missing Manual" by David Sawyer McFarland. This dude knows how to write; clearly, logically, and with very few typos :-)

After reading the whole book, I thought to myself, "Wow! HTML5 and CSS3 are an awesome combination." What particularly struck me was the fact that HTML5 is so clean and simple, and that CSS3 takes all the formatting stuff away from the HTML. Look at the source for these webpages — nothing but pure, clean, simple HTML.

Just like the old days.

So I took all my old web pages, and converted them. But the fun thing is that I did this using the venerable m4 macro processor. The above line of text, written in red using vi on a black background1, literally reads:

But the fun thing is that I did this using the venerable _CMD(m4) macro processor.

Notice how I used the _CMD(m4) macro to automatically generate the text for the <span class="command">m4</span> — I created what amount to various data types, like _CMD (for commands), _FUNC (for C functions), _VAR (for variables) and so on, that allow me to express a consistent style across plain ordinary text without having to do all the extra typing of <span> and "class=" over and over again. Here's the list:

m4_define(`_FUNC', `<span class="function">$1</span>')
m4_define(`_DTYPE', `<span class="dtype">$1</span>')
m4_define(`_CMD', `<span class="command">$1</span>')
m4_define(`_FNAME', `<span class="filename">$1</span>')
m4_define(`_CONST', `<span class="const">$1</span>')
m4_define(`_OPT', `<span class="opt">$1</span>')
m4_define(`_FIGURE', `<figure><img src="_IMAGE_PATH/$1" alt="$2"><figcaption>$2</figcaption></figure>')
m4_define(`_CODESTART', `<div class="code"><pre class="code">')
m4_define(`_CODEEND', `</div></pre>')

Escaping the quotes, less than, greater than, and such in the above was a bitch!

To that end, I have two files, a header.inc and a footer.inc which I include before and after the main text of these webpages (as m4 inputs), and m4 does the magic! The nice thing is, you can nest the macros. So if it turns out I use m4 a lot, and get tired of typing _CMD(m4), then I just create a new macro:

m4_define(`_M4', _CMD(m4))

And presto, I can now just type _M4 instead of _CMD(m4), like this: m4 :-) Ok, the above line really looks like this:

And presto, I can now just type `_M4' instead of `_CMD(m4)', like this:  _M4 :-)

But you get the idea.

Then, (another blast from the past), I use make to put it all together:

.SUFFIXES: .m4 .html
.m4.html: $(Common)
    m4 -D_LOCATION=coding -P <$*.m4 >$*.html

Beautiful. Here I'm using make to take care of defining the location of the subpages for me. This is an example of a Makefile from the coding subdirectory — it prepopulates the macro name _LOCATION with the value coding (and expressing that in the source text involved two nested sets of quotation marks!).


Note 1: It's like those idiotic smartphones that add "Sent from my iPhone" or "Sent using my left toe and arthritic thumb from my Crackberry while on a train". Who cares?