The UNIX system provides several macro processors. The shellcontains powerful mechanisms for text manipulation; the C language hasa macro preprocessor; document preparation tools like Troff, Pic, andEqn all have macros; and the m4 macro language is a general-purposetool useful in many contexts. m1, a basic macro language, is at leastthree notches below m4 (it may well be six below, but m2 was too hardto type).
m1's implementation grew from a dozen-line Awk program that providesrudimentary services to a limited but useful two-page program. But whyshould programmers study a kind of program built in the 1950s? A fewreasons I find convincing.
- Macro processors provide a fine playground for learning aboutprogramming techniques. (B.W. Kerrnighan and P.J. Plauger devote thefinal chapter of Software Tools in Pascal to the topic.)
- The implementation described here illustrates a number of devicesuseful in building Awk programs. (This article assumes familiarity withAwk; for more information, see
The Awk ProgrammingLanguage.)
- Investigating the design considerations of this simple macroprocessor can help you appreciate the macro languages you use. (Studiesindicate that programmers spend 1.7 percent of their time cursingunexpected side effects of macros.) If those reasons aren't goodenough, here's the most convincing argument: programmers have studiedmacro processors since the beginning of time, so you have to, too. It'sa rite of passage.
Given that the UNIX system on which I live already has so many macroprocessors, why did I even consider building one more? Most macrolanguages assume that the input is divided into tokens by the rules ofan underlying language. I recently faced a problem that didn't come insuch a neatly wrapped package. I needed to make substitutions in themiddle of strings, as in:
@define Condition under
You are clearly @Condition@worked.
The first line defines the string Condition , and in thesecond line that string (surrounded by the special @ characters) is replaced by the text under. Definitions must start on anew line with the string @define ; the name is the next fieldseparated by whitespace (blanks and tabs), and the replacement text isthe rest of the line. Replacements are insensitive to context: thestring @Condition@ is always replaced, even if it is insidequotes or not set apart by whitespace.
A simple macro language like this was sufficient to solve myimmediate problem. But once I had it, more applications of the macroprocessor started to wander across my terminal screen.
Jon Bentley is the author of Writing Efficient Programs, ProgrammingPearls, and More Programming Pearls: Confessions of a Coder, amongother books and papers