|
|
You can use built-in macros to perform these tasks or define your own macros. Built-in and user-defined macros work exactly the same way except that some of the built-in macros have side effects on the state of the process. A list of built-in macros appears on the m4(C) page.
The basic operation of m4 is to read every legal token (string of ASCII letters and digits and possibly supplementary characters) and determine if the token is the name of a macro. The name of the macro is replaced by its defining text, and the resulting string is pushed back onto the input to be rescanned. Macros may be called with arguments. The arguments are collected and substituted into the right places in the defining text before the defining text is rescanned.
Macro calls have the general form
name(arg1, arg2, ..., argn)If a macro name is not immediately followed by a left parenthesis, it is assumed to have no arguments. Leading unquoted blanks, tabs, and new-lines are ignored while collecting arguments. Left and right single quotes are used to quote strings. The value of a quoted string is the string stripped of the quotes.
When a macro name is recognized, its arguments are collected by searching for a matching right parenthesis. If fewer arguments are supplied than are in the macro definition, the trailing arguments are taken to be null. Macro evaluation proceeds normally during the collection of the arguments, and any commas or right parentheses that appear in the value of a nested call are as effective as those in the original input text. After argument collection, the value of the macro is pushed back onto the input stream and rescanned.
You invoke m4 with a command of the form
$ m4 file file fileEach argument file is processed in order. If there are no arguments or if an argument is a hyphen, the standard input is read. If you are eventually going to compile the m4 output, you could use a command something like this:
$ m4 file1.m4 > file1.c
You can use the -D option to define a macro on the m4 command line. Suppose you have two similar versions of a program. You might have a single m4 input file capable of generating the two output files. For example, file1.m4 could contain lines such as
if(VER, 1, do_something) if(VER, 2, do_something)Your makefile for the program might look like this:
file1.1.c : file1.m4 m4 -DVER=1 file1.m4 > file1.1.c ...You can use the -U option to ``undefine'' VER. If file1.m4 containsfile1.2.c : file1.m4 m4 -DVER=2 file1.m4 > file1.2.c ...
if(VER, 1, do_something) if(VER, 2, do_something) ifndef(VER, do_something)then your makefile would contain
file0.0.c : file1.m4 m4 -UVER file1.m4 > file1.0.c ...file1.1.c : file1.m4 m4 -DVER=1 file1.m4 > file1.1.c ...
file1.2.c : file1.m4 m4 -DVER=2 file1.m4 > file1.2.c ...