Script-based Website Maintenance



Basic content

You can use m4 to generate common text whenever necessary, but care must be taken to distinguish between macros to be expanded and literal text.

Literal text

All literal text should be enclosed in ` and ' to avoid it being interpreted as a macro by m4. In several cases, literal arguments to macros must be quoted that way twice, because m4 expands them once before they enter the macro, and once after they come out. Only some operands to built-in macros need only one pair of quotes: those which do not come out.

As an example, here is the definition of a trivial macro to create a paragraph using one of its arguments as the content:

define(`P', ``<P>'$1`</P>'')dnl

Only one set of quotes is needed around the macro name because it doesn't pass through the definition. However, the definition itself (the second argument) needs two for literal text — the outer pair delimits the argument and is stripped away before the definition is made, so doesn't ultimately form part of the definition. If you leave off one pair of quotes, the enclosed P will be expanded recursively, when you use the macro!

In summary, here are the arguments that need to be double-quoted:

Arguments to user-defined macros

For reasons which I forget right now, I dequote each $ argument reference within a definition, e.g.:

define(`P', ``<p>'$1`</p>'')dnl

This means that in uses of the macro, you must pass literal text quoted twice, for example:

P(``Hello, world!'')

You can probably get away with just using a single pair of quotes, but I'll leave that as an exercise for the reader. At least, I know that double-quoting works.

If anyone can shed light on this, do please contact me!

Ah! Here's a reason: you can avoid unnecessary macro expansions. Consider this single-quote example:

define(`test',`ifelse(`$1',`$2',``<p>Yes: $3</p>'', ``<p>No!</p>'')')dnl
define(`floop',``the words'errprint(`Macro floop used
')')dnl
test(1,0,`These are 'floop` of me')

…which yields:

<p>No!</p>

…but also prints out:

Macro floop used

…on the error output. The double-quote version:

define(`test',`ifelse(`$1',`$2',``<p>Yes: '$3`</p>'', ``<p>No!</p>'')')dnl
define(`floop',``the words'errprint(`Macro floop used
')')dnl
test(1,0,``These are 'floop` of me'')

…yields the same, but without the error message, because floop did not need to be expanded. This may have some value(?).


The following macros mainly involve XML character entities/‌references, so I keep them in a file include/xml.m4 which I include from etc/site.xml.m4.

Escaping m4

m4 uses the characters ' (apostrophe), ` (grave), , (comma) and $ (dollar) for special purposes. If you want to use them literally, these macros express them without m4 interpretation:

define(`APOS',``&#39;'')
define(`GRAV',``&#96;'')
define(`COMM',``&#44;'')
define(`DOLL',``&#36;'')

HTML Tidy will convert these into normal characters after leaving m4.

Only APOS and GRAV are usually necessary. Use them this way:

`It'APOS`s a nice day!'

…to produce:

It's a nice day!

Another possibility is to use the built-in macro changequote to change the quote strings to something less commonly encountered, possibly of more than one character, but you would still have to provide escapes for them. Or you could use changeword to change the syntax of macros so you don't have to quote everything, but that would make built-ins harder to access.

Uncertain about content?

You may be uncertain about how you should use (consistently) common terms or abbrieviations. If you define macros for them, you can change all uses at once.

For example, you might anticipate changing the title of a website, which appears on every page:

define(`SITENAME', ``My Excellent Website'')dnl
define(`SITEABBR', ``MEW'')dnl

Quotation marks

We can use m4 to quote text with the right quotation marks. The macro below, Qx, wraps its first argument between its second and third (the quotation marks):

define(`Qx',`$2`'$1`'$3')

(You may want to override this for specific media types. For example, see the HTML version of Qx.)

Here are some particular types of quotation marks:

define(`Q69',`Qx(`$1',``&lsquo;'',``&rsquo;'',shift($@))')
define(`DQ69',`Qx(`$1',``&ldquo;'',``&rdquo;'',shift($@))')
define(`QA',`Qx(`$1',``&lsaquo;'',``&rsaquo;'',shift($@))')
define(`DQA',`Qx(`$1',``&laquo;'',``&raquo;'',shift($@))')

Accented characters

In XML, you can express any character by its Unicode number, so if you cannot enter, for example, an accented character such as ‘ĥ’ directly, you can use &#292;.

Here are some macros for accented Esperanto characters:

define(`Cx',``&#264;'')
define(`cx',``&#265;'')
define(`Gx',``&#284;'')
define(`gx',``&#285;'')
define(`Hx',``&#292;'')
define(`hx',``&#293;'')
define(`Jx',``&#308;'')
define(`jx',``&#309;'')
define(`Sx',``&#348;'')
define(`sx',``&#349;'')
define(`Ux',``&#364;'')
define(`ux',``&#365;'')

Now you can write ‘eĥoŝanĝo ĉiuĵaŭde’ as `e'hx`o'sx`an'gx`o 'cx`iu'jx`a'ux`de'.

Some such characters break down into a base character and a combining one. For example, ‘ĥ’ can be expressed as h&#770;. So, with these macros:

define(`x',``&#770;'')
define(`w',``&#774;'')

…you can write ‘eĥoŝanĝo ĉiuĵaŭde’ as `eh'x`os'x`ang'x`o c'x`iuj'x`au'w`de'.

This form may help some browsers which cannot display the correct characters, because they may appear like this: ‘eh^os^ang^o c^iuj^au˘de’ or ‘eh?os?ang?o c?iuj?au?de’ instead of ‘e?o?an?o ?iu?a?de’.



Updated: 2008-Apr-04 11:46 GMT
Contact Steven Simpson

Ĉi tiu paĝo disponeblas ĉi-lingve, laŭ via krozila agordo.