m4

GNU M4 1.4.16 macro processor

Table of Contents


Next:  ,Up:  (dir)

GNU M4

This manual (28 February 2011) is for GNU M4 (version1.4.16), a package containing an implementation of the m4 macrolanguage.

Copyright © 1989-1994, 2004-2011 Free Software Foundation,Inc.

Permission is granted to copy, distribute and/or modify this documentunder the terms of the GNU Free Documentation License,Version 1.3 or any later version published by the Free SoftwareFoundation; with no Invariant Sections, no Front-Cover Texts, and noBack-Cover Texts. A copy of the license is included in the sectionentitled “GNU Free Documentation License.”

GNU m4 is an implementation of the traditional UNIX macroprocessor. It is mostly SVR4 compatible, although it has someextensions (for example, handling more than 9 positional parametersto macros).m4 also has builtin functions for includingfiles, running shell commands, doing arithmetic, etc. Autoconf needsGNUm4 for generating configure scripts, but not forrunning them.

GNU m4 was originally written by René Seindal, withsubsequent changes by François Pinard and other volunteerson the Internet. All names and email addresses can be found in thefilesm4-1.4.16/AUTHORS andm4-1.4.16/THANKS from the GNU M4distribution.

This is release 1.4.16. It is now considered stable: futurereleases in the 1.4.x series are only meant to fix bugs, increase speed,or improve documentation. However...

An experimental feature, which would improve m4 usefulness,allows for changing the syntax for what is aword in m4. You should use:

     ./configure --enable-changeword

if you want this feature compiled in. The current implementationslows downm4 considerably and is hardly acceptable. In thefuture, m4 2.0 will come with a different set of new featuresthat provide similar capabilities, but without the inefficiencies, sochangeword will go away andyou should not count on it.

--- The Detailed Node Listing ---

Introduction and preliminaries

Invoking m4

Lexical and syntactic conventions

How to invoke macros

How to define new macros

Conditionals, loops, and recursion

How to debug macros and input

Input control

File inclusion

Diverting and undiverting output

Macros for text handling

Macros for doing arithmetic

Macros for running shell commands

Miscellaneous builtin macros

Fast loading of frozen state

Compatibility with other versions of m4

Correct version of some examples

How to make copies of the overall M4 package

How to make copies of this manual

Indices of concepts and macros


Next:  ,Previous:  Top,Up:  Top

1 Introduction and preliminaries

This first chapter explains what GNU m4 is, where m4comes from, how to read and use this documentation, how to call them4 program, and how to report bugs about it. It concludes bygiving tips for reading the remainder of the manual.

The following chapters then detail all the features of the m4language.


Next:  ,Up:  Preliminaries

1.1 Introduction to m4

m4 is a macro processor, in the sense that it copies itsinput to the output, expanding macros as it goes. Macros are eitherbuiltin or user-defined, and can take any number of arguments. Besides just doing macro expansion, m4 has builtin functionsfor including named files, running shell commands, doing integerarithmetic, manipulating text in various ways, performing recursion,etc....m4 can be used either as a front-end to a compiler,or as a macro processor in its own right.

The m4 macro processor is widely available on all UNIXes, and hasbeen standardized by POSIX. Usually, only a small percentage of users are aware of its existence. However, those who find it often become committed users. Thepopularity of GNU Autoconf, which requires GNUm4 for generating configure scripts, is an incentivefor many to install it, while these people will not themselvesprogram inm4. GNU m4 is mostly compatible with theSystem V, Release 3 version, except for some minor differences. SeeCompatibility, for more details.

Some people find m4 to be fairly addictive. They first usem4 for simple problems, then take bigger and bigger challenges,learning how to write complex sets ofm4 macros along the way. Once really addicted, users pursue writing of sophisticatedm4applications even to solve simple problems, devoting more timedebugging theirm4 scripts than doing real work. Beware thatm4 may be dangerous for the health of compulsive programmers.


Next:  ,Previous:  Intro,Up:  Preliminaries

1.2 Historical references

GPM was an important ancestor ofm4. SeeC. Strachey: “A General Purpose Macro generator”, Computer Journal8,3 (1965), pp. 225 ff.GPM is also succinctly described intoDavid Gries classic “Compiler Construction for Digital Computers”.

The classic B. Kernighan and P.J. Plauger: “Software Tools”,Addison-Wesley, Inc. (1976) describes and implements a Unixmacro-processor language, which inspired Dennis Ritchie to writem3, a macro processor for the AP-3 minicomputer.

Kernighan and Ritchie then joined forces to develop the originalm4, as described in “The M4 Macro Processor”, BellLaboratories (1977). It had only 21 builtin macros.

While GPM was more pure, m4 is meant to deal withthe true intricacies of real life: macros can be recognized withoutbeing pre-announced, skipping whitespace or end-of-lines is easier,more constructs are builtin instead of derived, etc.

Originally, the Kernighan and Plauger macro-processor, and thenm3, formed the engine for the Rational FORTRAN preprocessor,that is, theRatfor equivalent of cpp. Later, m4was used as a front-end forRatfor, C and Cobol.

René Seindal released his implementation of m4, GNUm4,in 1990, with the aim of removing the artificial limitations in manyof the traditionalm4 implementations, such as maximum linelength, macro size, or number of macros.

The late Professor A. Dain Samples described and implemented a furtherevolution in the form ofM5: “User's Guide to the M5 MacroLanguage: 2nd edition”, Electronic Announcement on comp.compilersnewsgroup (1992).

François Pinard took over maintenance of GNU m4 in1992, until 1994 when he released GNUm4 1.4, which wasthe stable release for 10 years. It was at this time that GNUAutoconf decided to require GNUm4 as its underlyingengine, since all other implementations of m4 had too manylimitations.

More recently, in 2004, Paul Eggert released 1.4.1 and 1.4.2 whichaddressed some long standing bugs in the venerable 1.4 release. Then in2005, Gary V. Vaughan collected together the many patches toGNUm4 1.4 that were floating around the net andreleased 1.4.3 and 1.4.4. And in 2006, Eric Blake joined the team andprepared patches for the release of 1.4.5, 1.4.6, 1.4.7, and 1.4.8. More bug fixes were incorporated in 2007, with releases 1.4.9 and1.4.10. Eric continued with some portability fixes for 1.4.11 and1.4.12 in 2008, 1.4.13 in 2009, 1.4.14 and 1.4.15 in 2010, and 1.4.16 in2011.

Meanwhile, development has continued on new features for m4, suchas dynamic module loading and additional builtins. When complete,GNUm4 2.0 will start a new series of releases.


Next:  ,Previous:  History,Up:  Preliminaries

1.3 Problems and bugs

If you have problems with GNU M4 or think you've found a bug,please report it. Before reporting a bug, make sure you've actuallyfound a real bug. Carefully reread the documentation and see if itreally says you can do what you're trying to do. If it's not clearwhether you should be able to do something or not, report that too; it'sa bug in the documentation!

Before reporting a bug or trying to fix it yourself, try to isolate itto the smallest possible input file that reproduces the problem. Thensend us the input file and the exact resultsm4 gave you. Alsosay what you expected to occur; this will help us decide whether theproblem was really in the documentation.

Once you've got a precise problem, send e-mail tobug-m4@gnu.org. Please include the version number ofm4you are using. You can get this information with the commandm4 --version. Also provide details about the platform you areexecuting on.

Non-bug suggestions are always welcome as well. If you have questionsabout things that are unclear in the documentation or are just obscurefeatures, please report them too.


Previous:  Bugs,Up:  Preliminaries

1.4 Using this manual

This manual contains a number of examples ofm4 input and output,and a simple notation is used to distinguish input, output and errormessages fromm4. Examples are set out from the normal text, andshown in a fixed width font, like this

     This is an example of an example!

To distinguish input from output, all output from m4 is prefixedby the string ‘’, and all error messages by the string‘error-->’. When showing how command line options affect matters,the command line is shown with a prompt ‘$like this’,otherwise, you can assume that a simple m4 invocation will work. Thus:

     $ command line to invoke m4
     Example of input line
     ⇒Output line from m4
     error-->and an error message

The sequence ‘^D’ in an example indicates the end of the inputfile. The sequence ‘<NL>’ refers to the newline character. The majority of these examples are self-contained, and you can run themwith similar results by invoking m4 -d. In fact, the testsuitethat is bundled in the GNU M4 package consists of the examplesin this document! Some of the examples assume that your currentdirectory is located where you unpacked the installation, so if you planon following along, you may find it helpful to do this now:

     $ cd m4-1.4.16

As each of the predefined macros in m4 is described, a prototypecall of the macro will be shown, giving descriptive names to thearguments, e.g.,

— Composite: example ( string, [ count = ‘ 1 ] , [ argument ] ...)

This is a sample prototype. There is not really a macro namedexample, but this documents that if there were, it would be aComposite macro, rather than a Builtin. It requires at least oneargument,string. Remember that in m4, there must not be aspace between the macro name and the opening parenthesis, unless it wasintended to call the macro without any arguments. The brackets aroundcount andargument show that these arguments are optional. If count is omitted, the macro behaves as if count were ‘1’,whereas ifargument is omitted, the macro behaves as if it werethe empty string. A blank argument is not the same as an omittedargument. For example, ‘example(`a')’, ‘example(`a',`1')’,and ‘example(`a',`1',)’ would behave identically withcountset to ‘1’; while ‘example(`a',)’ and ‘example(`a',`')’would explicitly pass the empty string forcount. The ellipses(‘...’) show that the macro processes additional argumentsafterargument, rather than ignoring them.

All macro arguments in m4 are strings, but some are givenspecial interpretation, e.g., as numbers, file names, regularexpressions, etc. The documentation for each macro will state how theparameters are interpreted, and what happens if the argument cannot beparsed according to the desired interpretation. Unless specifiedotherwise, a parameter specified to be a number is parsed as a decimal,even if the argument has leading zeros; and parsing the empty string asa number results in 0 rather than an error, although a warning will beissued.

This document consistently writes and uses builtin, without ahyphen, as if it were an English word. This is how thebuiltinprimitive is spelled within m4.


Next:  ,Previous:  Preliminaries,Up:  Top

2 Invoking m4

The format of them4 command is:

     m4 [option...] [file...]

All options begin with ‘-’, or if long option names are used, with‘--’. A long option name need not be written completely, anyunambiguous prefix is sufficient. POSIX requiresm4 torecognize arguments intermixed with files, even whenPOSIXLY_CORRECT is set in the environment. Most options takeeffect at startup regardless of their position, but some are documentedbelow as taking effect after any files that occurred earlier in thecommand line. The argument -- is a marker to denote the end ofoptions.

With short options, options that do not take arguments may be combinedinto a single command line argument with subsequent options, optionswith mandatory arguments may be provided either as a single command lineargument or as two arguments, and options with optional arguments mustbe provided as a single argument. In other words,m4 -QPDfoo -d a -df is equivalent tom4 -Q -P -D foo -d -df -- ./a, although the latter form isconsidered canonical.

With long options, options with mandatory arguments may be provided withan equal sign (‘=’) in a single argument, or as two arguments, andoptions with optional arguments must be provided as a single argument. In other words, m4 --def foo --debug a is equivalent tom4 --define=foo --debug= -- ./a, although the latter form isconsidered canonical (not to mention more robust, in case a futureversion ofm4 introduces an option named --default).

m4 understands the following options, grouped by functionality.

2.1 Command line options for operation modes

Several options control the overall operation of m4:

--help
Print a help summary on standard output, then immediately exit m4 without reading any input files or performing any otheractions.
--version
Print the version number of the program on standard output, thenimmediately exit m4 without reading any input files orperforming any other actions.
-E --fatal-warnings
Controls the effect of warnings. If unspecified, then executioncontinues and exit status is unaffected when a warning is printed. Ifspecified exactly once, warnings become fatal; when one is issued,execution continues, but the exit status will be non-zero. If specifiedmultiple times, then execution halts with non-zero status the first timea warning is issued. The introduction of behavior levels is new to M41.4.9; for behavior consistent with earlier versions, you should specify -E twice.
-i --interactive -e
Makes this invocation of m4 interactive. This means that alloutput will be unbuffered, and interrupts will be ignored. Thespelling -e exists for compatibility with other m4implementations, and issues a warning because it may be withdrawn in afuture version of GNU M4.
-P --prefix-builtins
Internally modify all builtin macro names so they all start withthe prefix ‘ m4_’. For example, using this option, one should write‘ m4_define’ instead of ‘ define’, and ‘ m4___file__’instead of ‘ __file__’. This option has no effect if -Ris also specified.
-Q --quiet --silent
Suppress warnings, such as missing or superfluous arguments in macrocalls, or treating the empty string as zero.
--warn-macro-sequence [ = regexp ]
Issue a warning if the regular expression regexp has a non-emptymatch in any macro definition (either by define or pushdef). Empty matches are ignored; therefore, supplying theempty string as regexp disables any warning. If the optional regexp is not supplied, then the default regular expression is‘ \$\({[^}]*}\|[0-9][0-9]+\)’ (a literal ‘ $’ followed bymultiple digits or by an open brace), since these sequences willchange semantics in the default operation of GNU M4 2.0 (dueto a change in how more than 9 arguments in a macro definition will behandled, see Arguments). Providing an alternate regularexpression can provide a useful reverse lookup feature of findingwhere a macro is defined to have a given definition.
-W regexp --word-regexp= regexp
Use regexp as an alternative syntax for macro names. Thisexperimental option will not be present in all GNU m4implementations (see Changeword).


Next:  ,Previous:  Operation modes,Up:  Invoking m4

2.2 Command line options for preprocessor features

Several options allowm4 to behave more like a preprocessor. Macro definitions and deletions can be made on the command line, thesearch path can be altered, and the output file can track where theinput came from. These features occur with the following options:

-D name [ = value ] --define= name [ = value ]
This enters name into the symbol table. If ‘ =value’ ismissing, the value is taken to be the empty string. The value canbe any string, and the macro can be defined to take arguments, just asif it was defined from within the input. This option may be given morethan once; order with respect to file names is significant, andredefining the same name loses the previous value.
-I directory --include= directory
Make m4 search directory for included files that are notfound in the current working directory. See Search Path, for moredetails. This option may be given more than once.
-s --synclines
Generate synchronization lines, for use by the C preprocessor or othersimilar tools. Order is significant with respect to file names. Thisoption is useful, for example, when m4 is used as afront end to a compiler. Source file name and line number informationis conveyed by directives of the form ‘ #linelinenum"file"’, which are inserted as needed into the middle of theoutput. Such directives mean that the following line originated or wasexpanded from the contents of input file file at line linenum. The ‘ "file"’ part is often omitted whenthe file name did not change from the previous directive.

Synchronization directives are always given on complete lines bythemselves. When a synchronization discrepancy occurs in the middle ofan output line, the associated synchronization directive is delayeduntil the next newline that does not occur in the middle of a quotedstring or comment.

          define(`twoline', `1
          2')
          ⇒#line 2 "stdin"
          ⇒
          changecom(`/*', `*/')
          ⇒
          define(`comment', `/*1
          2*/')
          ⇒#line 5
          ⇒
          dnl no line
          hello
          ⇒#line 7
          ⇒hello
          twoline
          ⇒1
          ⇒#line 8
          ⇒2
          comment
          ⇒/*1
          ⇒2*/
          one comment `two
          three'
          ⇒#line 10
          ⇒one /*1
          ⇒2*/ two
          ⇒three
          goodbye
          ⇒#line 12
          ⇒goodbye

-U name --undefine= name
This deletes any predefined meaning name might have. Obviously,only predefined macros can be deleted in this way. This option may begiven more than once; undefining a name that does not have adefinition is silently ignored. Order is significant with respect tofile names.


Next:  ,Previous:  Preprocessor features,Up:  Invoking m4

2.3 Command line options for limits control

There are some limits within m4 that can be tuned. Forcompatibility,m4 also accepts some options that control limitsin other implementations, but which are automatically unbounded (limitedonly by your hardware and operating system constraints) in GNUm4.

-g --gnu
Enable all the extensions in this implementation. In this release ofM4, this option is always on by default; it is currently only usefulwhen overriding a prior use of --traditional. However, havingGNU behavior as default makes it impossible to write astrictly POSIX-compliant client that avoids all incompatibleGNU M4 extensions, since such a client would have to use thenon-POSIX command-line option to force full POSIXbehavior. Thus, a future version of M4 will be changed to implicitlyuse the option --traditional if the environment variable POSIXLY_CORRECT is set. Projects that intentionally useGNU extensions should consider using --gnu to statetheir intentions, so that the project will not mysteriously break if theuser upgrades to a newer M4 and has POSIXLY_CORRECT set in theirenvironment.
-G --traditional
Suppress all the extensions made in this implementation, compared to theSystem V version. See Compatibility, for a list of these.
-H num --hashsize= num
Make the internal hash table for symbol lookup be num entries big. For better performance, the number should be prime, but this is notchecked. The default is 509 entries. It should not be necessary toincrease this value, unless you define an excessive number of macros.
-L num --nesting-limit= num
Artificially limit the nesting of macro calls to num levels,stopping program execution if this limit is ever exceeded. When notspecified, nesting defaults to unlimited on platforms that can detectstack overflow, and to 1024 levels otherwise. A value of zero meansunlimited; but then heavily nested code could potentially cause a stackoverflow.

The precise effect of this option is more correctly associatedwith textual nesting than dynamic recursion. It has been usefulwhen some complexm4 input was generated by mechanical means, andalso in diagnosing recursive algorithms that do not scale well. Most users never need to change this option from its default.

This option does not have the ability to break endlessrescanning loops, since these do not necessarily consume much memoryor stack space. Through clever usage of rescanning loops, one canrequest complex, time-consuming computations from m4 with usefulresults. Putting limitations in this area would breakm4 power. There are many pathological cases: ‘define(`a', `a')a’ isonly the simplest example (but seeCompatibility). Expecting GNUm4 to detect these would be a little like expecting a compilersystem to detect and diagnose endless loops: it is a quitehardproblem in general, if not undecidable!

-B num -S num -T num
These options are present for compatibility with System V m4, butdo nothing in this implementation. They may disappear in futurereleases, and issue a warning to that effect.
-N num --diversions= num
These options are present only for compatibility with previousversions of GNU m4, and were controlling the number ofpossible diversions which could be used at the same time. They do nothing,because there is no fixed limit anymore. They may disappear in futurereleases, and issue a warning to that effect.


Next:  ,Previous:  Limits control,Up:  Invoking m4

2.4 Command line options for frozen state

GNU m4 comes with a feature of freezing internal state(see Frozen files). This can be used to speed up m4execution when reusing a common initialization script.

-F file --freeze-state= file
Once execution is finished, write out the frozen state on the specified file. It is conventional, but not required, for file to endin ‘ .m4f’.
-R file --reload-state= file
Before execution starts, recover the internal state from the specifiedfrozen file. The options -D, -U, and -t take effect after state is reloaded, but before the inputfiles are read.


Next:  ,Previous:  Frozen state,Up:  Invoking m4

2.5 Command line options for debugging

Finally, there are several options for aiding in debugging m4scripts.

-d [ flags ] --debug [ = flags ]
Set the debug-level according to the flags flags. The debug-levelcontrols the format and amount of information presented by the debuggingfunctions. See Debug Levels, for more details on the format andmeaning of flags. If omitted, flags defaults to ‘ aeq’.
--debugfile [ = file ] -o file --error-output= file
Redirect dumpdef output, debug messages, and trace output to thenamed file. Warnings, error messages, and errprint outputare still printed to standard error. If these options are not used, orif file is unspecified (only possible for --debugfile),debug output goes to standard error; if file is the empty string,debug output is discarded. See Debug Output, for more details. Theoption --debugfile may be given more than once, and order issignificant with respect to file names. The spellings -o and --error-output are misleading and inconsistent with otherGNU tools; for now they are silently accepted as synonyms of --debugfile and only recognized once, but in a future versionof M4, using them will cause a warning to be issued.
-l num --arglength= num
Restrict the size of the output generated by macro tracing to numcharacters per trace line. If unspecified or zero, output isunlimited. See Debug Levels, for more details.
-t name --trace= name
This enables tracing for the macro name, at any point where it isdefined. name need not be defined when this option is given. This option may be given more than once, and order is significant withrespect to file names. See Trace, for more details.


Previous:  Debugging options,Up:  Invoking m4

2.6 Specifying input files on the command line

The remaining arguments on the command line are taken to be input filenames. If no names are present, standard input is read. A filename of - is taken to mean standard input. It isconventional, but not required, for input files to end in ‘.m4’.

The input files are read in the sequence given. Standard input can beread more than once, so the file name- may appear multiple timeson the command line; this makes a difference when input is from aterminal or other special file type. It is an error if an input fileends in the middle of argument collection, a comment, or a quotedstring.

The options --define (-D),--undefine(-U),--synclines (-s), and--trace(-t) only take effect after processing input from any filenames that occur earlier on the command line. For example, assume thefilefoo contains:

     $ cat foo
     bar

The text ‘bar’ can then be redefined over multiple uses offoo:

     $ m4 -Dbar=hello foo -Dbar=world foo
     ⇒hello
     ⇒world

If none of the input files invoked m4exit (see M4exit), theexit status of m4 will be 0 for success, 1 for general failure(such as problems with reading an input file), and 63 for versionmismatch (seeUsing frozen files).

If you need to read a file whose name starts with a -, you canspecify it as ‘./-file’, or use-- to mark the end ofoptions.


Next:  ,Previous:  Invoking m4,Up:  Top

3 Lexical and syntactic conventions

As m4 reads its input, it separates it intotokens. Atoken is either a name, a quoted string, or any single character, thatis not a part of either a name or a string. Input tom4 can alsocontain comments. GNU m4 does not yet understandmultibyte locales; all operations are byte-oriented rather thancharacter-oriented (although if your locale uses a single byteencoding, such asISO-8859-1, you will not notice a difference). However, m4 is eight-bit clean, so you canuse non-ascii characters in quoted strings (seeChangequote),comments (see Changecom), and macro names (seeIndir), with theexception of the nul character (the zero byte ‘'\0'’).


Next:  ,Up:  Syntax

3.1 Macro names

A name is any sequence of letters, digits, and the character ‘_’(underscore), where the first character is not a digit.m4 willuse the longest such sequence found in the input. If a name has amacro definition, it will be subject to macro expansion(seeMacros). Names are case-sensitive.

Examples of legal names are: ‘foo’, ‘_tmp’, and ‘name01’.


Next:  ,Previous:  Names,Up:  Syntax

3.2 Quoting input to m4

A quoted string is a sequence of characters surrounded by quotestrings, defaulting to‘`’ and ‘'’, where the nested begin and end quotes within thestring are balanced. The value of a string token is the text, with onelevel of quotes stripped off. Thus

     `'
     ⇒

is the empty string, and double-quoting turns into single-quoting.

     ``quoted''
     ⇒`quoted'

The quote characters can be changed at any time, using the builtin macrochangequote. SeeChangequote, for more information.


Next:  ,Previous:  Quoted strings,Up:  Syntax

3.3 Comments in m4 input

Comments in m4 are normally delimited by the characters ‘#’and newline. All characters between the comment delimiters are ignored,but the entire comment (including the delimiters) is passed through tothe output—comments are not discarded by m4.

Comments cannot be nested, so the first newline after a ‘#’ endsthe comment. The commenting effect of the begin-comment stringcan be inhibited by quoting it.

     $ m4
     `quoted text' # `commented text'
     ⇒quoted text # `commented text'
     `quoting inhibits' `#' `comments'
     ⇒quoting inhibits # comments

The comment delimiters can be changed to any string at any time, usingthe builtin macrochangecom. See Changecom, for moreinformation.


Next:  ,Previous:  Comments,Up:  Syntax

3.4 Other kinds of input tokens

Any character, that is neither a part of a name, nor of a quoted string,nor a comment, is a token by itself. When not in the context of macroexpansion, all of these tokens are just copied to output. However,during macro expansion, whitespace characters (space, tab, newline,formfeed, carriage return, vertical tab), parentheses (‘(’ and‘)’), comma (‘,’), and dollar (‘$’) have additionalroles, explained later.


Previous:  Other tokens,Up:  Syntax

3.5 How m4 copies input to output

As m4 reads the input token by token, it will copy each tokendirectly to the output immediately.

The exception is when it finds a word with a macro definition. In thatcase m4 will calculate the macro's expansion, possibly readingmore input to get the arguments. It then inserts the expansion in frontof the remaining input. In other words, the resulting text from a macrocall will be read and parsed into tokens again.

m4 expands a macro as soon as possible. If it finds a macro callwhen collecting the arguments to another, it will expand the second callfirst. This process continues until there are no more macro calls toexpand and all the input has been consumed.

For a running example, examine how m4 handles this input:

     format(`Result is %d', eval(`2**15'))

First, m4 sees that the token ‘format’ is a macro name, soit collects the tokens ‘(’, ‘`Result is %d'’, ‘,’,and ‘ ’, before encountering another potential macro. Sureenough, ‘eval’ is a macro name, so the nested argument collectionpicks up ‘(’, ‘`2**15'’, and ‘)’, invoking the eval macrowith the lone argument of ‘2**15’. The expansion of‘eval(2**15)’ is ‘32768’, which is then rescanned as the fivetokens ‘3’, ‘2’, ‘7’, ‘6’, and ‘8’; andcombined with the next ‘)’, the format macro now has all itsarguments, as if the user had typed:

     format(`Result is %d', 32768)

The format macro expands to ‘Result is 32768’, and we have anotherround of scanning for the tokens ‘Result’, ‘ ’,‘is’, ‘ ’, ‘3’, ‘2’, ‘7’, ‘6’, and‘8’. None of these are macros, so the final output is

     ⇒Result is 32768

As a more complicated example, we will contrast an actual codeexample from the Gnulib project1,showing both a buggy approach and the desired results. The user desiresto output a shell assignment statement that takes its argument and turnsit into a shell variable by converting it to uppercase and prepending aprefix. The original attempt looks like this:

     changequote([,])dnl
     define([gl_STRING_MODULE_INDICATOR],
       [
         dnl comment
         GNULIB_]translit([$1],[a-z],[A-Z])[=1
       ])dnl
       gl_STRING_MODULE_INDICATOR([strcase])
     ⇒  
     ⇒        GNULIB_strcase=1
     ⇒  

Oops – the argument did not get capitalized. And although the manualis not able to easily show it, both lines that appear empty actuallycontain two trailing spaces. By stepping through the parse, it is easyto see what happened. First,m4 sees the token‘changequote’, which it recognizes as a macro, followed by‘(’, ‘[’, ‘,’, ‘]’, and ‘)’ to form theargument list. The macro expands to the empty string, but changes thequoting characters to something more useful for generating shell code(unbalanced ‘`’ and ‘'’ appear all the time in shell scripts,but unbalanced ‘[]’ tend to be rare). Also in the first line,m4 sees the token ‘dnl’, which it recognizes as a builtinmacro that consumes the rest of the line, resulting in no output forthat line.

The second line starts a macro definition. m4 sees the token‘define’, which it recognizes as a macro, followed by a ‘(’,‘[gl_STRING_MODULE_INDICATOR]’, and ‘,’. Because an unquotedcomma was encountered, the first argument is known to be the expansionof the single-quoted string token, or ‘gl_STRING_MODULE_INDICATOR’. Next,m4 sees ‘<NL>’, ‘ ’, and ‘ ’, but thiswhitespace is discarded as part of argument collection. Then comes arather lengthy single-quoted string token, ‘[<NL> dnlcomment<NL> GNULIB_]’. This is followed by the token‘translit’, which m4 recognizes as a macro name, so a nestedmacro expansion has started.

The arguments to the translit are found by the tokens ‘(’,‘[$1]’, ‘,’, ‘[a-z]’, ‘,’, ‘[A-Z]’, and finally‘)’. All three string arguments are expanded (or in other words,the quotes are stripped), and since neither ‘$’ nor ‘1’ needcapitalization, the result of the macro is ‘$1’. This expansion isrescanned, resulting in the two literal characters ‘$’ and‘1’.

Scanning of the outer macro resumes, and picks up with‘[=1<NL> ]’, and finally ‘)’. The collected pieces ofexpanded text are concatenated, with the end result that the macro‘gl_STRING_MODULE_INDICATOR’ is now defined to be the sequence‘<NL> dnl comment<NL> GNULIB_$1=1<NL>’. Once again, ‘dnl’ is recognized and avoids a newline in the output.

The final line is then parsed, beginning with ‘ ’ and ‘ ’that are output literally. Then ‘gl_STRING_MODULE_INDICATOR’ isrecognized as a macro name, with an argument list of ‘(’,‘[strcase]’, and ‘)’. Since the definition of the macrocontains the sequence ‘$1’, that sequence is replaced with theargument ‘strcase’ prior to starting the rescan. The rescan sees‘<NL>’ and four spaces, which are output literally, then‘dnl’, which discards the text ‘ comment<NL>’. Nextcomes four more spaces, also output literally, and the token‘GNULIB_strcase’, which resulted from the earlier parametersubstitution. Since that is not a macro name, it is output literally,followed by the literal tokens ‘=’, ‘1’, ‘<NL>’, andtwo more spaces. Finally, the original ‘<NL>’ seen after themacro invocation is scanned and output literally.

Now for a corrected approach. This rearranges the use of newlines andwhitespace so that less whitespace is output (which, although harmlessto shell scripts, can be visually unappealing), and fixes the quotingissues so that the capitalization occurs when the macro‘gl_STRING_MODULE_INDICATOR’ is invoked, rather then when it isdefined. It also adds another layer of quoting to the first argument oftranslit, to ensure that the output will be rescanned as a stringrather than a potential uppercase macro name needing further expansion.

     changequote([,])dnl
     define([gl_STRING_MODULE_INDICATOR],
       [dnl comment
       GNULIB_[]translit([[$1]], [a-z], [A-Z])=1dnl
     ])dnl
       gl_STRING_MODULE_INDICATOR([strcase])
     ⇒    GNULIB_STRCASE=1

The parsing of the first line is unchanged. The second line sees thename of the macro to define, then sees the discarded ‘<NL>’and two spaces, as before. But this time, the next token is‘[dnl comment<NL> GNULIB_[]translit([[$1]], [a-z],[A-Z])=1dnl<NL>]’, which includes nested quotes, followed by‘)’ to end the macro definition and ‘dnl’ to skip thenewline. No early expansion of translit occurs, so the entirestring becomes the definition of the macro.

The final line is then parsed, beginning with two spaces that areoutput literally, and an invocation ofgl_STRING_MODULE_INDICATOR with the argument ‘strcase’. Again, the ‘$1’ in the macro definition is substituted prior torescanning. Rescanning first encounters ‘dnl’, and discards‘ comment<NL>’. Then two spaces are output literally. Nextcomes the token ‘GNULIB_’, but that is not a macro, so it isoutput literally. The token ‘[]’ is an empty string, so it doesnot affect output. Then the token ‘translit’ is encountered.

This time, the arguments to translit are parsed as ‘(’,‘[[strcase]]’, ‘,’, ‘’, ‘[a-z]’, ‘,’, ‘’,‘[A-Z]’, and ‘)’. The two spaces are discarded, and thetranslit results in the desired result ‘[STRCASE]’. This isrescanned, but since it is a string, the quotes are stripped and theonly output is a literal ‘STRCASE’. Then the scanner sees ‘=’ and ‘1’, which are outputliterally, followed by ‘dnl’ which discards the rest of thedefinition ofgl_STRING_MODULE_INDICATOR. The newline at theend of output is the literal ‘<NL>’ that appeared after theinvocation of the macro.

The order in which m4 expands the macros can be further exploredusing the trace facilities of GNUm4 (see Trace).


Next:  ,Previous:  Syntax,Up:  Top

4 How to invoke macros

This chapter covers macro invocation, macro arguments and how macroexpansion is treated.

4.1 Macro invocation

Macro invocations has one of the forms

     name

which is a macro invocation without any arguments, or

     name(arg1, arg2, ..., argn)

which is a macro invocation with n arguments. Macros can have anynumber of arguments. All arguments are strings, but different macrosmight interpret the arguments in different ways.

The opening parenthesis must follow the name directly, withno spaces in between. If it does not, the macro is called with noarguments at all.

For a macro call to have no arguments, the parentheses must beleft out. The macro call

     name()

is a macro call with one argument, which is the empty string, not a callwith no arguments.


Next:  ,Previous:  Invocation,Up:  Macros

4.2 Preventing macro invocation

An innovation of the m4 language, compared to some of itspredecessors (like Strachey'sGPM, for example), is the abilityto recognize macro calls without resorting to any special, prefixedinvocation character. While generally useful, this feature mightsometimes be the source of spurious, unwanted macro calls. So, GNUm4 offers several mechanisms or techniques for inhibiting therecognition of names as macro calls.

First of all, many builtin macros cannot meaningfully be called withoutarguments. As a GNU extension, for any of these macros,whenever an opening parenthesis does not immediately follow their name,the builtin macro call is not triggered. This solves the most usualcases, like for ‘include’ or ‘eval’. Later in this document,the sentence “This macro is recognized only with parameters” refers tothis specific provision of GNU M4, also known as a blindbuiltin macro. For the builtins defined by POSIX that bearthis disclaimer, POSIX specifically states that invoking thosebuiltins without arguments is unspecified, because many otherimplementations simply invoke the builtin as though it were given oneempty argument instead.

     $ m4
     eval
     ⇒eval
     eval(`1')
     ⇒1

There is also a command line option (--prefix-builtins, or-P, seeInvoking m4) that renames allbuiltin macros with a prefix of ‘m4_’ at startup. The option hasno effect whatsoever on user defined macros. For example, with this option,one has to writem4_dnl and even m4_m4exit. It also hasno effect on whether a macro requires parameters.

     $ m4 -P
     eval
     ⇒eval
     eval(`1')
     ⇒eval(1)
     m4_eval
     ⇒m4_eval
     m4_eval(`1')
     ⇒1

Another alternative is to redefine problematic macros to a name lesslikely to cause conflicts, SeeDefinitions.

If your version of GNU m4 has the changeword featurecompiled in, it offers far more flexibility in specifying thesyntax of macro names, both builtin or user-defined. SeeChangeword,for more information on this experimental feature.

Of course, the simplest way to prevent a name from being interpretedas a call to an existing macro is to quote it. The remainder ofthis section studies a little more deeply how quoting affects macroinvocation, and how quoting can be used to inhibit macro invocation.

Even if quoting is usually done over the whole macro name, it can alsobe done over only a few characters of this name (provided, of course,that the unquoted portions are not also a macro). It is also possibleto quote the empty string, but this works onlyinside the name. For example:

     `divert'
     ⇒divert
     `d'ivert
     ⇒divert
     di`ver't
     ⇒divert
     div`'ert
     ⇒divert

all yield the string ‘divert’. While in both:

     `'divert
     ⇒
     divert`'
     ⇒

the divert builtin macro will be called, which expands to theempty string.

The output of macro evaluations is always rescanned. In the followingexample, the input ‘x`'y’ yields the string ‘bCD’, exactly asifm4has been given ‘substr(ab`'cde, `1', `3')’ as input:

     define(`cde', `CDE')
     ⇒
     define(`x', `substr(ab')
     ⇒
     define(`y', `cde, `1', `3')')
     ⇒
     x`'y
     ⇒bCD

Unquoted strings on either side of a quoted string are subject tobeing recognized as macro names. In the following example, quoting theempty string allows for the secondmacro to be recognized as such:

     define(`macro', `m')
     ⇒
     macro(`m')macro
     ⇒mmacro
     macro(`m')`'macro
     ⇒mm

Quoting may prevent recognizing as a macro name the concatenation of amacro expansion with the surrounding characters. In this example:

     define(`macro', `di$1')
     ⇒
     macro(`v')`ert'
     ⇒divert
     macro(`v')ert
     ⇒

the input will produce the string ‘divert’. When the quotes wereremoved, thedivert builtin was called instead.


Next:  ,Previous:  Inhibiting Invocation,Up:  Macros

4.3 Macro arguments

When a name is seen, and it has a macro definition, it will be expandedas a macro.

If the name is followed by an opening parenthesis, the arguments will becollected before the macro is called. If too few arguments aresupplied, the missing arguments are taken to be the empty string. However, some builtins are documented to behave differently for amissing optional argument than for an explicit empty string. If thereare too many arguments, the excess arguments are ignored. Unquotedleading whitespace is stripped off all arguments, but whitespacegenerated by a macro expansion or occurring after a macro that expandedto an empty string remains intact. Whitespace includes space, tab,newline, carriage return, vertical tab, and formfeed.

     define(`macro', `$1')
     ⇒
     macro( unquoted leading space lost)
     ⇒unquoted leading space lost
     macro(` quoted leading space kept')
     ⇒ quoted leading space kept
     macro(
      divert `unquoted space kept after expansion')
     ⇒ unquoted space kept after expansion
     macro(macro(`
     ')`whitespace from expansion kept')
     ⇒
     ⇒whitespace from expansion kept
     macro(`unquoted trailing whitespace kept'
     )
     ⇒unquoted trailing whitespace kept
     ⇒

Normallym4 will issue warnings if a builtin macro is calledwith an inappropriate number of arguments, but it can be suppressed withthe--quiet command line option (or --silent, or-Q, seeInvoking m4). For userdefined macros, there is no check of the number of arguments given.

     $ m4
     index(`abc')
     error-->m4:stdin:1: Warning: too few arguments to builtin `index'
     ⇒0
     index(`abc',)
     ⇒0
     index(`abc', `b', `ignored')
     error-->m4:stdin:3: Warning: excess arguments to builtin `index' ignored
     ⇒1
     $ m4 -Q
     index(`abc')
     ⇒0
     index(`abc',)
     ⇒0
     index(`abc', `b', `ignored')
     ⇒1

Macros are expanded normally during argument collection, and whatevercommas, quotes and parentheses that might show up in the resultingexpanded text will serve to define the arguments as well. Thus, iffoo expands to ‘, b, c’, the macro call

     bar(a foo, d)

is a macro call with four arguments, which are ‘a’, ‘b’,‘c’ and ‘d’. To understand why the first argument containswhitespace, remember that unquoted leading whitespace is never partof an argument, but trailing whitespace always is.

It is possible for a macro's definition to change during argumentcollection, in which case the expansion uses the definition that was ineffect at the time the opening ‘(’ was seen.

     define(`f', `1')
     ⇒
     f(define(`f', `2'))
     ⇒1
     f
     ⇒2

It is an error if the end of file occurs while collecting arguments.

     hello world
     ⇒hello world
     define(
     ^D
     error-->m4:stdin:2: ERROR: end of file in argument list


Next:  ,Previous:  Macro Arguments,Up:  Macros

4.4 On Quoting Arguments to macros

Each argument has unquoted leading whitespace removed. Within eachargument, all unquoted parentheses must match. For example, iffoo is a macro,

     foo(() (`(') `(')

is a macro call, with one argument, whose value is ‘() (() (’. Commas separate arguments, except when they occur inside quotes,comments, or unquoted parentheses. SeePseudo Arguments, forexamples.

It is common practice to quote all arguments to macros, unless you aresure you want the arguments expanded. Thus, in the aboveexample with the parentheses, the `right' way to do it is like this:

     foo(`() (() (')

It is, however, in certain cases necessary (because nested expansionmust occur to create the arguments for the outer macro) or convenient(because it uses fewer characters) to leave out quotes for somearguments, and there is nothing wrong in doing it. It just makes life abit harder, if you are not careful to follow a consistent quoting style. For consistency, this manual follows the rule of thumb that each layerof parentheses introduces another layer of single quoting, except whenshowing the consequences of quoting rules. This is done even when thequoted string cannot be a macro, such as with integers when you have notchanged the syntax viachangeword (see Changeword).

The quoting rule of thumb of one level of quoting per parentheses has anice property: when a macro name appears inside parentheses, you candetermine when it will be expanded. If it is not quoted, it will beexpanded prior to the outer macro, so that its expansion becomes theargument. If it is single-quoted, it will be expanded after the outermacro. And if it is double-quoted, it will be used as literal textinstead of a macro name.

     define(`active', `ACT, IVE')
     ⇒
     define(`show', `$1 $1')
     ⇒
     show(active)
     ⇒ACT ACT
     show(`active')
     ⇒ACT, IVE ACT, IVE
     show(``active'')
     ⇒active active


Previous:  Quoting Arguments,Up:  Macros

4.5 Macro expansion

When the arguments, if any, to a macro call have been collected, themacro is expanded, and the expansion text is pushed back onto the input(unquoted), and reread. The expansion text from one macro call mighttherefore result in more macros being called, if the calls are included,completely or partially, in the first macro calls' expansion.

Taking a very simple example, if foo expands to ‘bar’, andbar expands to ‘Hello’, the input

     $ m4 -Dbar=Hello -Dfoo=bar
     foo
     ⇒Hello

will expand first to ‘bar’, and when this is reread andexpanded, into ‘Hello’.


Next:  ,Previous:  Macros,Up:  Top

5 How to define new macros

Macros can be defined, redefined and deleted in several different ways. Also, it is possible to redefine a macro without losing a previousvalue, and bring back the original value at a later time.


Next:  ,Up:  Definitions

5.1 Defining a macro

The normal way to define or redefine macros is to use the builtindefine:

— Builtin: define ( name, [ expansion ])

Defines name to expand to expansion. Ifexpansion is not given, it is taken to be empty.

The expansion of define is void. The macro define is recognized only with parameters.

The following example defines the macro foo to expand to the text‘Hello World.’.

     define(`foo', `Hello world.')
     ⇒
     foo
     ⇒Hello world.

The empty line in the output is there because the newline is nota part of the macro definition, and it is consequently copied tothe output. This can be avoided by use of the macrodnl. See Dnl, for details.

The first argument to define should be quoted; otherwise, if themacro is already defined, you will be defining a different macro. Thisexample shows the problems with underquoting, since we did not want toredefineone:

     define(foo, one)
     ⇒
     define(foo, two)
     ⇒
     one
     ⇒two

GNU m4 normally replaces only thetopmostdefinition of a macro if it has several definitions from pushdef(seePushdef). Some other implementations of m4 replace alldefinitions of a macro withdefine. See Incompatibilities,for more details.

As a GNU extension, the first argument to define doesnot have to be a simple word. It can be any text string, even the empty string. A macro with anon-standard name cannot be invoked in the normal way, as the name isnot recognized. It can only be referenced by the builtins indir(see Indir) anddefn (see Defn).

Arrays and associative arrays can be simulated by using non-standardmacro names.

— Composite: array ( index)
— Composite: array_set ( index, [ value ])

Provide access to entries within an array. array reads the entryat locationindex, and array_set assigns value tolocation index.

     define(`array', `defn(format(``array[%d]'', `$1'))')
     ⇒
     define(`array_set', `define(format(``array[%d]'', `$1'), `$2')')
     ⇒
     array_set(`4', `array element no. 4')
     ⇒
     array_set(`17', `array element no. 17')
     ⇒
     array(`4')
     ⇒array element no. 4
     array(eval(`10 + 7'))
     ⇒array element no. 17

Change the ‘%d’ to ‘%s’ and it is an associative array.


Next:  ,Previous:  Define,Up:  Definitions

5.2 Arguments to macros

Macros can have arguments. Thenth argument is denoted by$n in the expansion text, and is replaced by thenth actualargument, when the macro is expanded. Replacement of arguments happensbefore rescanning, regardless of how many nesting levels of quotingappear in the expansion. Here is an example of a macro withtwo arguments.

— Composite: exch ( arg1, arg2)

Expands to arg2 followed by arg1, effectively exchangingtheir order.

     define(`exch', `$2, $1')
     ⇒
     exch(`arg1', `arg2')
     ⇒arg2, arg1

This can be used, for example, if you like the arguments todefine to be reversed.

     define(`exch', `$2, $1')
     ⇒
     define(exch(``expansion text'', ``macro''))
     ⇒
     macro
     ⇒expansion text

See Quoting Arguments, for an explanation of the double quotes. (You should try and improve this example so that clients ofexchdo not have to double quote; or see Answers).

As a special case, the zeroth argument, $0, is always the nameof the macro being expanded.

     define(`test', ``Macro name: $0'')
     ⇒
     test
     ⇒Macro name: test

If you want quoted text to appear as part of the expansion text,remember that quotes can be nested in quoted strings. Thus, in

     define(`foo', `This is macro `foo'.')
     ⇒
     foo
     ⇒This is macro foo.

The ‘foo’ in the expansion text isnot expanded, since it isa quoted string, and not a name.

GNUm4 allows the number following the ‘$’ toconsist of one or more digits, allowing macros to have any number ofarguments. The extension of accepting multiple digits is incompatiblewith POSIX, and is different than traditional implementationsof m4, which only recognize one digit. Therefore, futureversions of GNU M4 will phase out this feature. To portablyaccess beyond the ninth argument, you can use theargn macrodocumented later (see Shift).

POSIX also states that ‘$’ followed immediately by‘{’ in a macro definition is implementation-defined. This versionof M4 passes the literal characters ‘${’ through unchanged, but M42.0 will implement an optional feature similar to sh, where‘${11}’ expands to the eleventh argument, to replace the currentrecognition of ‘$11’. Meanwhile, if you want to guarantee that youwill get a literal ‘${’ in output when expanding a macro, evenwhen you upgrade to M4 2.0, you can use nested quoting to youradvantage:

     define(`foo', `single quoted $`'{1} output')
     ⇒
     define(`bar', ``double quoted $'`{2} output'')
     ⇒
     foo(`a', `b')
     ⇒single quoted ${1} output
     bar(`a', `b')
     ⇒double quoted ${2} output

To help you detect places in your M4 input files that might change inbehavior due to the changed behavior of M4 2.0, you can use the--warn-macro-sequence command-line option (seeInvoking m4) with the default regular expression. This willadd a warning any time a macro definition includes ‘$’ followed bymultiple digits, or by ‘{’. The warning is not enabled bydefault, because it triggers a number of warnings in Autoconf 2.61 (andAutoconf uses-E to treat warnings as errors), and because itwill still be possible to restore older behavior in M4 2.0.

     $ m4 --warn-macro-sequence
     define(`foo', `$001 ${1} $1')
     error-->m4:stdin:1: Warning: definition of `foo' contains sequence `$001'
     error-->m4:stdin:1: Warning: definition of `foo' contains sequence `${1}'
     ⇒
     foo(`bar')
     ⇒bar ${1} bar


Next:  ,Previous:  Arguments,Up:  Definitions

5.3 Special arguments to macros

There is a special notation for the number of actual arguments supplied,and for all the actual arguments.

The number of actual arguments in a macro call is denoted by $#in the expansion text.

— Composite: nargs ( ...)

Expands to a count of the number of arguments supplied.

     define(`nargs', `$#')
     ⇒
     nargs
     ⇒0
     nargs()
     ⇒1
     nargs(`arg1', `arg2', `arg3')
     ⇒3
     nargs(`commas can be quoted, like this')
     ⇒1
     nargs(arg1#inside comments, commas do not separate arguments
     still arg1)
     ⇒1
     nargs((unquoted parentheses, like this, group arguments))
     ⇒1

Remember that ‘#’ defaults to the comment character; if you forgetquotes to inhibit the comment behavior, your macro definition may notend where you expected.

     dnl Attempt to define a macro to just `$#'
     define(underquoted, $#)
     oops)
     ⇒
     underquoted
     ⇒0)
     ⇒oops

The notation $* can be used in the expansion text to denote allthe actual arguments, unquoted, with commas in between. For example

     define(`echo', `$*')
     ⇒
     echo(arg1,    arg2, arg3 , arg4)
     ⇒arg1,arg2,arg3 ,arg4

Often each argument should be quoted, and the notation $@ handlesthat. It is just like$*, except that it quotes each argument. A simple example of that is:

     define(`echo', `$@')
     ⇒
     echo(arg1,    arg2, arg3 , arg4)
     ⇒arg1,arg2,arg3 ,arg4

Where did the quotes go? Of course, they were eaten, when the expandedtext were reread bym4. To show the difference, try

     define(`echo1', `$*')
     ⇒
     define(`echo2', `$@')
     ⇒
     define(`foo', `This is macro `foo'.')
     ⇒
     echo1(foo)
     ⇒This is macro This is macro foo..
     echo1(`foo')
     ⇒This is macro foo.
     echo2(foo)
     ⇒This is macro foo.
     echo2(`foo')
     ⇒foo

See Trace, if you do not understand this. As another example of thedifference, remember that comments encountered in arguments are passeduntouched to the macro, and that quoting disables comments.

     define(`echo1', `$*')
     ⇒
     define(`echo2', `$@')
     ⇒
     define(`foo', `bar')
     ⇒
     echo1(#foo'foo
     foo)
     ⇒#foo'foo
     ⇒bar
     echo2(#foo'foo
     foo)
     ⇒#foobar
     ⇒bar'

A ‘$’ sign in the expansion text, that is not followed by anythingm4 understands, is simply copied to the macro expansion, as anyother text is.

     define(`foo', `$$$ hello $$$')
     ⇒
     foo
     ⇒$$$ hello $$$

If you want a macro to expand to something like ‘$12’, thejudicious use of nested quoting can put a safe character between the$ and the next character, relying on the rescanning to remove thenested quote. This will preventm4 from interpreting the$ sign as a reference to an argument.

     define(`foo', `no nested quote: $1')
     ⇒
     foo(`arg')
     ⇒no nested quote: arg
     define(`foo', `nested quote around $: `$'1')
     ⇒
     foo(`arg')
     ⇒nested quote around $: $1
     define(`foo', `nested empty quote after $: $`'1')
     ⇒
     foo(`arg')
     ⇒nested empty quote after $: $1
     define(`foo', `nested quote around next character: $`1'')
     ⇒
     foo(`arg')
     ⇒nested quote around next character: $1
     define(`foo', `nested quote around both: `$1'')
     ⇒
     foo(`arg')
     ⇒nested quote around both: arg


Next:  ,Previous:  Pseudo Arguments,Up:  Definitions

5.4 Deleting a macro

A macro definition can be removed withundefine:

— Builtin: undefine ( name...)

For each argument, remove the macro name. The macro names mustnecessarily be quoted, since they will be expanded otherwise.

The expansion of undefine is void. The macro undefine is recognized only with parameters.

     foo bar blah
     ⇒foo bar blah
     define(`foo', `some')define(`bar', `other')define(`blah', `text')
     ⇒
     foo bar blah
     ⇒some other text
     undefine(`foo')
     ⇒
     foo bar blah
     ⇒foo other text
     undefine(`bar', `blah')
     ⇒
     foo bar blah
     ⇒foo bar blah

Undefining a macro inside that macro's expansion is safe; the macrostill expands to the definition that was in effect at the ‘(’.

     define(`f', ``$0':$1')
     ⇒
     f(f(f(undefine(`f')`hello world')))
     ⇒f:f:f:hello world
     f(`bye')
     ⇒f(bye)

It is not an error for name to have no macro definition. In thatcase,undefine does nothing.


Next:  ,Previous:  Undefine,Up:  Definitions

5.5 Renaming macros

It is possible to rename an already defined macro. To do this, you needthe builtin defn:

— Builtin: defn ( name...)

Expands to the quoted definition of each name. If anargument is not a defined macro, the expansion for that argument isempty.

If name is a user-defined macro, the quoted definition is simplythe quoted expansion text. If, instead, there is only onenameand it is a builtin, theexpansion is a special token, which points to the builtin's internaldefinition. This token is only meaningful as the second argument todefine (andpushdef), and is silently converted to anempty string in most other contexts. Combining a builtin with anythingelse is not supported; a warning is issued and the builtin is omittedfrom the final expansion.

The macro defn is recognized only with parameters.

Its normal use is best understood through an example, which shows how torenameundefine to zap:

     define(`zap', defn(`undefine'))
     ⇒
     zap(`undefine')
     ⇒
     undefine(`zap')
     ⇒undefine(zap)

In this way, defn can be used to copy macro definitions, and alsodefinitions of builtin macros. Even if the original macro is removed,the other name can still be used to access the definition.

The fact that macro definitions can be transferred also explains why youshould use$0, rather than retyping a macro's name in itsdefinition:

     define(`foo', `This is `$0'')
     ⇒
     define(`bar', defn(`foo'))
     ⇒
     bar
     ⇒This is bar

Macros used as string variables should be referred through defn,to avoid unwanted expansion of the text:

     define(`string', `The macro dnl is very useful
     ')
     ⇒
     string
     ⇒The macro 
     defn(`string')
     ⇒The macro dnl is very useful
     ⇒

However, it is important to remember that m4 rescanning is purelytextual. If an unbalanced end-quote string occurs in a macrodefinition, the rescan will see that embedded quote as the terminationof the quoted string, and the remainder of the macro's definition willbe rescanned unquoted. Thus it is a good idea to avoid unbalancedend-quotes in macro definitions or arguments to macros.

     define(`foo', a'a)
     ⇒
     define(`a', `A')
     ⇒
     define(`echo', `$@')
     ⇒
     foo
     ⇒A'A
     defn(`foo')
     ⇒aA'
     echo(foo)
     ⇒AA'

On the other hand, it is possible to exploit the fact that defncan concatenate multiple macros prior to the rescanning phase, in orderto join the definitions of macros that, in isolation, have unbalancedquotes. This is particularly useful when one has used several macros toaccumulate text that M4 should rescan as a whole. In the example below,note how the use ofdefn on l in isolation opens a string,which is not closed until the next line; but used onl andr together results in nested quoting.

     define(`l', `<[>')define(`r', `<]>')
     ⇒
     changequote(`[', `]')
     ⇒
     defn([l])defn([r])
     ])
     ⇒<[>]defn([r])
     ⇒)
     defn([l], [r])
     ⇒<[>][<]>

Usingdefn to generate special tokens for builtin macros outsideof expected contexts can sometimes trigger warnings. But most of thetime, such tokens are silently converted to the empty string.

     $ m4 -d
     defn(`defn')
     ⇒
     define(defn(`divnum'), `cannot redefine a builtin token')
     error-->m4:stdin:2: Warning: define: invalid macro name ignored
     ⇒
     divnum
     ⇒0
     len(defn(`divnum'))
     ⇒0

Also note that defn with multiple arguments can only join textmacros, not builtins, although a future version of GNU M4 maylift this restriction.

     $ m4 -d
     define(`a', `A')define(`AA', `b')
     ⇒
     traceon(`defn', `define')
     ⇒
     defn(`a', `divnum', `a')
     error-->m4:stdin:3: Warning: cannot concatenate builtin `divnum'
     error-->m4trace: -1- defn(`a', `divnum', `a') -> ``A'`A''
     ⇒AA
     define(`mydivnum', defn(`divnum', `divnum'))mydivnum
     error-->m4:stdin:4: Warning: cannot concatenate builtin `divnum'
     error-->m4:stdin:4: Warning: cannot concatenate builtin `divnum'
     error-->m4trace: -2- defn(`divnum', `divnum')
     error-->m4trace: -1- define(`mydivnum', `')
     ⇒
     traceoff(`defn', `define')
     ⇒


Next:  ,Previous:  Defn,Up:  Definitions

5.6 Temporarily redefining macros

It is possible to redefine a macro temporarily, reverting to theprevious definition at a later time. This is done with the builtinspushdef andpopdef:

— Builtin: pushdef ( name, [ expansion ])
— Builtin: popdef ( name...)

Analogous to define and undefine.

These macros work in a stack-like fashion. A macro is temporarilyredefined withpushdef, which replaces an existing definition ofname, while saving the previous definition, before the new one isinstalled. If there is no previous definition,pushdef behavesexactly like define.

If a macro has several definitions (of which only one is accessible),the topmost definition can be removed withpopdef. If there isno previous definition, popdef behaves likeundefine.

The expansion of both pushdef and popdef is void. The macrospushdef and popdef are recognized only withparameters.

     define(`foo', `Expansion one.')
     ⇒
     foo
     ⇒Expansion one.
     pushdef(`foo', `Expansion two.')
     ⇒
     foo
     ⇒Expansion two.
     pushdef(`foo', `Expansion three.')
     ⇒
     pushdef(`foo', `Expansion four.')
     ⇒
     popdef(`foo')
     ⇒
     foo
     ⇒Expansion three.
     popdef(`foo', `foo')
     ⇒
     foo
     ⇒Expansion one.
     popdef(`foo')
     ⇒
     foo
     ⇒foo

If a macro with several definitions is redefined with define, thetopmost definition isreplaced with the new definition. If it isremoved with undefine,all the definitions are removed,and not only the topmost one. However, POSIX allows otherimplementations that treatdefine as replacing an entire stackof definitions with a single new definition, so to be portable to otherimplementations, it may be worth explicitly usingpopdef andpushdef rather than relying on the GNU behavior ofdefine.

     define(`foo', `Expansion one.')
     ⇒
     foo
     ⇒Expansion one.
     pushdef(`foo', `Expansion two.')
     ⇒
     foo
     ⇒Expansion two.
     define(`foo', `Second expansion two.')
     ⇒
     foo
     ⇒Second expansion two.
     undefine(`foo')
     ⇒
     foo
     ⇒foo

Local variables within macros are made withpushdef andpopdef. At the start of the macro a new definition is pushed,within the macro it is manipulated and at the end it is popped,revealing the former definition.

It is possible to temporarily redefine a builtin with pushdefand defn.


Next:  ,Previous:  Pushdef,Up:  Definitions

5.7 Indirect call of macros

Any macro can be called indirectly withindir:

— Builtin: indir ( name, [ args... ])

Results in a call to the macro name, which is passed therest of the argumentsargs. If name is not defined, anerror message is printed, and the expansion is void.

The macro indir is recognized only with parameters.

This can be used to call macros with computed or “invalid”names (define allows such names to be defined):

     define(`$$internal$macro', `Internal macro (name `$0')')
     ⇒
     $$internal$macro
     ⇒$$internal$macro
     indir(`$$internal$macro')
     ⇒Internal macro (name $$internal$macro)

The point is, here, that larger macro packages can have private macrosdefined, that will not be called by accident. They canonly becalled through the builtin indir.

One other point to observe is that argument collection occurs beforeindir invokesname, so if argument collection changes thevalue of name, that will be reflected in the final expansion. This is different than the behavior when invoking macros directly,where the definition that was in effect before argument collection isused.

     $ m4 -d
     define(`f', `1')
     ⇒
     f(define(`f', `2'))
     ⇒1
     indir(`f', define(`f', `3'))
     ⇒3
     indir(`f', undefine(`f'))
     error-->m4:stdin:4: undefined macro `f'
     ⇒

When handed the result of defn (see Defn) as one of itsarguments,indir defers to the invoked name for whether atoken representing a builtin is recognized or flattened to the emptystring.

     $ m4 -d
     indir(defn(`defn'), `divnum')
     error-->m4:stdin:1: Warning: indir: invalid macro name ignored
     ⇒
     indir(`define', defn(`defn'), `divnum')
     error-->m4:stdin:2: Warning: define: invalid macro name ignored
     ⇒
     indir(`define', `foo', defn(`divnum'))
     ⇒
     foo
     ⇒0
     indir(`divert', defn(`foo'))
     error-->m4:stdin:5: empty string treated as 0 in builtin `divert'
     ⇒


Previous:  Indir,Up:  Definitions

5.8 Indirect call of builtins

Builtin macros can be called indirectly withbuiltin:

— Builtin: builtin ( name, [ args... ])

Results in a call to the builtin name, which is passed therest of the argumentsargs. If name does not name abuiltin, an error message is printed, and the expansion is void.

The macro builtin is recognized only with parameters.

This can be used even if name has been given another definitionthat has covered the original, or been undefined so that no macromaps to the builtin.

     pushdef(`define', `hidden')
     ⇒
     undefine(`undefine')
     ⇒
     define(`foo', `bar')
     ⇒hidden
     foo
     ⇒foo
     builtin(`define', `foo', defn(`divnum'))
     ⇒
     foo
     ⇒0
     builtin(`define', `foo', `BAR')
     ⇒
     foo
     ⇒BAR
     undefine(`foo')
     ⇒undefine(foo)
     foo
     ⇒BAR
     builtin(`undefine', `foo')
     ⇒
     foo
     ⇒foo

The name argument only matches the original name of the builtin,even when the--prefix-builtins option (or -P,seeInvoking m4) is in effect. This is differentfrom indir, which only tracks current macro names.

     $ m4 -P
     m4_builtin(`divnum')
     ⇒0
     m4_builtin(`m4_divnum')
     error-->m4:stdin:2: undefined builtin `m4_divnum'
     ⇒
     m4_indir(`divnum')
     error-->m4:stdin:3: undefined macro `divnum'
     ⇒
     m4_indir(`m4_divnum')
     ⇒0

Note that indir and builtin can be used to invoke builtinswithout arguments, even when they normally require parameters to berecognized; but it will provoke a warning, and result in a void expansion.

     builtin
     ⇒builtin
     builtin()
     error-->m4:stdin:2: undefined builtin `'
     ⇒
     builtin(`builtin')
     error-->m4:stdin:3: Warning: too few arguments to builtin `builtin'
     ⇒
     builtin(`builtin',)
     error-->m4:stdin:4: undefined builtin `'
     ⇒
     builtin(`builtin', ``'
     ')
     error-->m4:stdin:5: undefined builtin ``'
     error-->'
     ⇒
     indir(`index')
     error-->m4:stdin:7: Warning: too few arguments to builtin `index'
     ⇒


Next:  ,Previous:  Definitions,Up:  Top

6 Conditionals, loops, and recursion

Macros, expanding to plain text, perhaps with arguments, are not quiteenough. We would like to have macros expand to different things, basedon decisions taken at run-time. For that, we need some kind of conditionals. Also, we would like to have some kind of loop construct, so we could dosomething a number of times, or while some condition is true.


Next:  ,Up:  Conditionals

6.1 Testing if a macro is defined

There are two different builtin conditionals inm4. The first isifdef:

— Builtin: ifdef ( name, string-1, [ string-2 ])

If name is defined as a macro, ifdef expands tostring-1, otherwise tostring-2. If string-2 isomitted, it is taken to be the empty string (according to the normalrules).

The macro ifdef is recognized only with parameters.

     ifdef(`foo', ``foo' is defined', ``foo' is not defined')
     ⇒foo is not defined
     define(`foo', `')
     ⇒
     ifdef(`foo', ``foo' is defined', ``foo' is not defined')
     ⇒foo is defined
     ifdef(`no_such_macro', `yes', `no', `extra argument')
     error-->m4:stdin:4: Warning: excess arguments to builtin `ifdef' ignored
     ⇒no


Next:  ,Previous:  Ifdef,Up:  Conditionals

6.2 If-else construct, or multibranch

The other conditional,ifelse, is much more powerful. It can beused as a way to introduce a long comment, as an if-else construct, oras a multibranch, depending on the number of arguments supplied:

— Builtin: ifelse ( comment)
— Builtin: ifelse ( string-1, string-2, equal, [ not-equal ])
— Builtin: ifelse ( string-1, string-2, equal-1, string-3, string-4, equal-2,..., [ not-equal ])

Used with only one argument, the ifelse simply discards it andproduces no output.

If called with three or four arguments, ifelse expands intoequal, ifstring-1 and string-2 are equal (characterfor character), otherwise it expands tonot-equal. A final fifthargument is ignored, after triggering a warning.

If called with six or more arguments, and string-1 andstring-2 are equal,ifelse expands into equal-1,otherwise the first three arguments are discarded and the processingstarts again.

The macro ifelse is recognized only with parameters.

Using only one argument is a common m4 idiom for introducing ablock comment, as an alternative to repeatedly usingdnl. Thisspecial usage is recognized by GNU m4, so that in thiscase, the warning about missing arguments is never triggered.

     ifelse(`some comments')
     ⇒
     ifelse(`foo', `bar')
     error-->m4:stdin:2: Warning: too few arguments to builtin `ifelse'
     ⇒

Using three or four arguments provides decision points.

     ifelse(`foo', `bar', `true')
     ⇒
     ifelse(`foo', `foo', `true')
     ⇒true
     define(`foo', `bar')
     ⇒
     ifelse(foo, `bar', `true', `false')
     ⇒true
     ifelse(foo, `foo', `true', `false')
     ⇒false

Notice how the first argument was used unquoted; it is common to comparethe expansion of a macro with a string. With this macro, you can nowreproduce the behavior of blind builtins, where the macro is recognizedonly with arguments.

     define(`foo', `ifelse(`$#', `0', ``$0'', `arguments:$#')')
     ⇒
     foo
     ⇒foo
     foo()
     ⇒arguments:1
     foo(`a', `b', `c')
     ⇒arguments:3

For an example of a way to make defining blind macros easier, seeComposition.

The macroifelse can take more than four arguments. If given morethan four arguments,ifelse works like a case or switchstatement in traditional programming languages. Ifstring-1 andstring-2 are equal, ifelse expands intoequal-1, otherwisethe procedure is repeated with the first three arguments discarded. Thiscalls for an example:

     ifelse(`foo', `bar', `third', `gnu', `gnats')
     error-->m4:stdin:1: Warning: excess arguments to builtin `ifelse' ignored
     ⇒gnu
     ifelse(`foo', `bar', `third', `gnu', `gnats', `sixth')
     ⇒
     ifelse(`foo', `bar', `third', `gnu', `gnats', `sixth', `seventh')
     ⇒seventh
     ifelse(`foo', `bar', `3', `gnu', `gnats', `6', `7', `8')
     error-->m4:stdin:4: Warning: excess arguments to builtin `ifelse' ignored
     ⇒7

Naturally, the normal case will be slightly more advanced than theseexamples. A common use ofifelse is in macros implementing loopsof various kinds.


Next:  ,Previous:  Ifelse,Up:  Conditionals

6.3 Recursion in m4

There is no direct support for loops inm4, but macros can berecursive. There is no limit on the number of recursion levels, otherthan those enforced by your hardware and operating system.

Loops can be programmed using recursion and the conditionals describedpreviously.

There is a builtin macro, shift, which can, among other things,be used for iterating through the actual arguments to a macro:

— Builtin: shift ( arg1, ...)

Takes any number of arguments, and expands to all its arguments exceptarg1, separated by commas, with each argument quoted.

The macro shift is recognized only with parameters.

     shift
     ⇒shift
     shift(`bar')
     ⇒
     shift(`foo', `bar', `baz')
     ⇒bar,baz

An example of the use of shift is this macro:

— Composite: reverse ( ...)

Takes any number of arguments, and reverses their order.

It is implemented as:

     define(`reverse', `ifelse(`$#', `0', , `$#', `1', ``$1'',
                               `reverse(shift($@)), `$1'')')
     ⇒
     reverse
     ⇒
     reverse(`foo')
     ⇒foo
     reverse(`foo', `bar', `gnats', `and gnus')
     ⇒and gnus, gnats, bar, foo

While not a very interesting macro, it does show how simple loops can bemade withshift, ifelse and recursion. It also showsthat shift is usually used with ‘$@’. Another example ofthis is an implementation of a short-circuiting conditional operator.

— Composite: cond ( test-1, string-1, equal-1, [ test-2 ] , [ string-2 ] , [ equal-2 ] ,..., [ not-equal ])

Similar to ifelse, where an equal comparison between the firsttwo strings results in the third, otherwise the first three argumentsare discarded and the process repeats. The difference is that eachtest-<n> is expanded only when it is encountered. This means thatevery third argument to cond is normally given one more level ofquoting than the corresponding argument toifelse.

Here is the implementation of cond, along with a demonstration ofhow it can short-circuit the side effects inside. Notice howall the unquoted side effects happen regardless of how many comparisonsare made withifelse, compared with only the relevant effectswith cond.

     define(`cond',
     `ifelse(`$#', `1', `$1',
             `ifelse($1, `$2', `$3',
                     `$0(shift(shift(shift($@))))')')')dnl
     define(`side', `define(`counter', incr(counter))$1')dnl
     define(`example1',
     `define(`counter', `0')dnl
     ifelse(side(`$1'), `yes', `one comparison: ',
            side(`$1'), `no', `two comparisons: ',
            side(`$1'), `maybe', `three comparisons: ',
            `side(`default answer: ')')counter')dnl
     define(`example2',
     `define(`counter', `0')dnl
     cond(`side(`$1')', `yes', `one comparison: ',
          `side(`$1')', `no', `two comparisons: ',
          `side(`$1')', `maybe', `three comparisons: ',
          `side(`default answer: ')')counter')dnl
     example1(`yes')
     ⇒one comparison: 3
     example1(`no')
     ⇒two comparisons: 3
     example1(`maybe')
     ⇒three comparisons: 3
     example1(`feeling rather indecisive today')
     ⇒default answer: 4
     example2(`yes')
     ⇒one comparison: 1
     example2(`no')
     ⇒two comparisons: 2
     example2(`maybe')
     ⇒three comparisons: 3
     example2(`feeling rather indecisive today')
     ⇒default answer: 4

Another common task that requires iteration is joining a list ofarguments into a single string.

— Composite: join ( [ separator ] , [ args... ])
— Composite: joinall ( [ separator ] , [ args... ])

Generate a single-quoted string, consisting of each arg separatedbyseparator. While joinall always outputs aseparator between arguments,join avoids theseparator for an empty arg.

Here are some examples of its usage, based on the implementationm4-1.4.16/examples/join.m4 distributed in thispackage:

     $ m4 -I examples
     include(`join.m4')
     ⇒
     join,join(`-'),join(`-', `'),join(`-', `', `')
     ⇒,,,
     joinall,joinall(`-'),joinall(`-', `'),joinall(`-', `', `')
     ⇒,,,-
     join(`-', `1')
     ⇒1
     join(`-', `1', `2', `3')
     ⇒1-2-3
     join(`', `1', `2', `3')
     ⇒123
     join(`-', `', `1', `', `', `2', `')
     ⇒1-2
     joinall(`-', `', `1', `', `', `2', `')
     ⇒-1---2-
     join(`,', `1', `2', `3')
     ⇒1,2,3
     define(`nargs', `$#')dnl
     nargs(join(`,', `1', `2', `3'))
     ⇒1

Examining the implementation shows some interesting points about severalm4 programming idioms.

     $ m4 -I examples
     undivert(`join.m4')dnl
     ⇒divert(`-1')
     ⇒# join(sep, args) - join each non-empty ARG into a single
     ⇒# string, with each element separated by SEP
     ⇒define(`join',
     ⇒`ifelse(`$#', `2', ``$2'',
     ⇒  `ifelse(`$2', `', `', ``$2'_')$0(`$1', shift(shift($@)))')')
     ⇒define(`_join',
     ⇒`ifelse(`$#$2', `2', `',
     ⇒  `ifelse(`$2', `', `', ``$1$2'')$0(`$1', shift(shift($@)))')')
     ⇒# joinall(sep, args) - join each ARG, including empty ones,
     ⇒# into a single string, with each element separated by SEP
     ⇒define(`joinall', ``$2'_$0(`$1', shift($@))')
     ⇒define(`_joinall',
     ⇒`ifelse(`$#', `2', `', ``$1$3'$0(`$1', shift(shift($@)))')')
     ⇒divert`'dnl

First, notice that this implementation creates helper macros_join and_joinall. This division of labor makes iteasier to output the correct number ofseparator instances:join and joinall are responsible for the first argument,without a separator, while_join and _joinall areresponsible for all remaining arguments, always outputting a separatorwhen outputting an argument.

Next, observe how join decides to iterate to itself, because thefirstarg was empty, or to output the argument and swap over to_join. If the argument is non-empty, then the nestedifelse results in an unquoted ‘_’, which is concatenatedwith the ‘$0’ to form the next macro name to invoke. Thejoinall implementation is simpler since it does not have tosuppress emptyarg; it always executes once then defers to_joinall.

Another important idiom is the idea that separator is reused foreach iteration. Each iteration has one less argument, but rather thandiscarding ‘$1’ by iterating with$0(shift($@)), the macrodiscards ‘$2’ by using$0(`$1', shift(shift($@))).

Next, notice that it is possible to compare more than one condition in asingleifelse test. The test of ‘$#$2’ against ‘2’allows_join to iterate for two separate reasons—either thereare still more than two arguments, or there are exactly two argumentsbut the last argument is not empty.

Finally, notice that these macros require exactly two arguments toterminate recursion, but that they still correctly result in emptyoutput when given noargs (i.e., zero or one macro argument). Onthe first pass when there are too few arguments, theshiftresults in no output, but leaves an empty string to serve as therequired second argument for the second pass. Put another way,‘`$1', shift($@)’ is not the same as ‘$@’, since only theformer guarantees at least two arguments.

Sometimes, a recursive algorithm requires adding quotes to each element,or treating multiple arguments as a single element:

— Composite: quote ( ...)
— Composite: dquote ( ...)
— Composite: dquote_elt ( ...)

Takes any number of arguments, and adds quoting. With quote,only one level of quoting is added, effectively removing whitespaceafter commas and turning multiple arguments into a single string. Withdquote, two levels of quoting are added, one around each element,and one around the list. And with dquote_elt, two levels ofquoting are added around each element.

An actual implementation of these three macros is distributed asm4-1.4.16/examples/quote.m4 in this package. First,let's examine their usage:

     $ m4 -I examples
     include(`quote.m4')
     ⇒
     -quote-dquote-dquote_elt-
     ⇒----
     -quote()-dquote()-dquote_elt()-
     ⇒--`'-`'-
     -quote(`1')-dquote(`1')-dquote_elt(`1')-
     ⇒-1-`1'-`1'-
     -quote(`1', `2')-dquote(`1', `2')-dquote_elt(`1', `2')-
     ⇒-1,2-`1',`2'-`1',`2'-
     define(`n', `$#')dnl
     -n(quote(`1', `2'))-n(dquote(`1', `2'))-n(dquote_elt(`1', `2'))-
     ⇒-1-1-2-
     dquote(dquote_elt(`1', `2'))
     ⇒``1'',``2''
     dquote_elt(dquote(`1', `2'))
     ⇒``1',`2''

The last two lines show that when given two arguments, dquoteresults in one string, whiledquote_elt results in two. Now,examine the implementation. Note thatquote anddquote_elt make decisions based on their number of arguments, sothat when called without arguments, they result in nothing instead of aquoted empty string; this is so that it is possible to distinguishbetween no arguments and an empty first argument. dquote, on theother hand, results in a string no matter what, since it is stillpossible to tell whether it was invoked without arguments based on theresulting string.

     $ m4 -I examples
     undivert(`quote.m4')dnl
     ⇒divert(`-1')
     ⇒# quote(args) - convert args to single-quoted string
     ⇒define(`quote', `ifelse(`$#', `0', `', ``$*'')')
     ⇒# dquote(args) - convert args to quoted list of quoted strings
     ⇒define(`dquote', ``$@'')
     ⇒# dquote_elt(args) - convert args to list of double-quoted strings
     ⇒define(`dquote_elt', `ifelse(`$#', `0', `', `$#', `1', ```$1''',
     ⇒                             ```$1'',$0(shift($@))')')
     ⇒divert`'dnl

It is worth pointing out that ‘quote(args)’ is more efficientthan ‘joinall(`,',args)’ for producing the same output.

One more useful macro based onshift allows portably selectingan arbitrary argument (usually greater than the ninth argument), withoutrelying on the GNU extension of multi-digit arguments(seeArguments).

— Composite: argn ( n, ...)

Expands to argument n out of the remaining arguments. nmust be a positive number. Usually invoked as‘argn(`n',$@)’.

It is implemented as:

     define(`argn', `ifelse(`$1', 1, ``$2'',
       `argn(decr(`$1'), shift(shift($@)))')')
     ⇒
     argn(`1', `a')
     ⇒a
     define(`foo', `argn(`11', $@)')
     ⇒
     foo(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k', `l')
     ⇒k


Next:  ,Previous:  Shift,Up:  Conditionals

6.4 Iteration by counting

Here is an example of a loop macro that implements a simple for loop.

— Composite: forloop ( iterator, start, end, text)

Takes the name in iterator, which must be a valid macro name, andsuccessively assign it each integer value fromstart to end,inclusive. For each assignment to iterator, appendtext tothe expansion of the forloop. text may refer toiterator. Any definition ofiterator prior to thisinvocation is restored.

It can, for example, be used for simple counting:

     $ m4 -I examples
     include(`forloop.m4')
     ⇒
     forloop(`i', `1', `8', `i ')
     ⇒1 2 3 4 5 6 7 8 

For-loops can be nested, like:

     $ m4 -I examples
     include(`forloop.m4')
     ⇒
     forloop(`i', `1', `4', `forloop(`j', `1', `8', ` (i, j)')
     ')
     ⇒ (1, 1) (1, 2) (1, 3) (1, 4) (1, 5) (1, 6) (1, 7) (1, 8)
     ⇒ (2, 1) (2, 2) (2, 3) (2, 4) (2, 5) (2, 6) (2, 7) (2, 8)
     ⇒ (3, 1) (3, 2) (3, 3) (3, 4) (3, 5) (3, 6) (3, 7) (3, 8)
     ⇒ (4, 1) (4, 2) (4, 3) (4, 4) (4, 5) (4, 6) (4, 7) (4, 8)
     ⇒

The implementation of the forloop macro is fairlystraightforward. Theforloop macro itself is simply a wrapper,which saves the previous definition of the first argument, calls theinternal macro_forloop, and re-establishes the saveddefinition of the first argument.

The macro _forloop expands the fourth argument once, andtests to see if the iterator has reached the final value. If it hasnot finished, it increments the iterator (using the predefined macroincr, seeIncr), and recurses.

Here is an actual implementation of forloop, distributed asm4-1.4.16/examples/forloop.m4 in this package:

     $ m4 -I examples
     undivert(`forloop.m4')dnl
     ⇒divert(`-1')
     ⇒# forloop(var, from, to, stmt) - simple version
     ⇒define(`forloop', `pushdef(`$1', `$2')_forloop($@)popdef(`$1')')
     ⇒define(`_forloop',
     ⇒       `$4`'ifelse($1, `$3', `', `define(`$1', incr($1))$0($@)')')
     ⇒divert`'dnl

Notice the careful use of quotes. Certain macro arguments are leftunquoted, each for its own reason. Try to find outwhy thesearguments are left unquoted, and see what happens if they are quoted. (As presented, these two macros are useful but not very robust forgeneral use. They lack even basic error handling for cases likestart less thanend, end not numeric, oriterator not being a macro name. See if you can improve thesemacros; or seeAnswers).


Next:  ,Previous:  Forloop,Up:  Conditionals

6.5 Iteration by list contents

Here is an example of a loop macro that implements list iteration.

— Composite: foreach ( iterator, paren-list, text)
— Composite: foreachq ( iterator, quote-list, text)

Takes the name in iterator, which must be a valid macro name, andsuccessively assign it each value fromparen-list orquote-list. In foreach, paren-list is acomma-separated list of elements contained in parentheses. Inforeachq,quote-list is a comma-separated list of elementscontained in a quoted string. For each assignment toiterator,append text to the overall expansion. text may refer toiterator. Any definition ofiterator prior to thisinvocation is restored.

As an example, this displays each word in a list inside of a sentence,using an implementation offoreach distributed asm4-1.4.16/examples/foreach.m4, andforeachqin m4-1.4.16/examples/foreachq.m4.

     $ m4 -I examples
     include(`foreach.m4')
     ⇒
     foreach(`x', (foo, bar, foobar), `Word was: x
     ')dnl
     ⇒Word was: foo
     ⇒Word was: bar
     ⇒Word was: foobar
     include(`foreachq.m4')
     ⇒
     foreachq(`x', `foo, bar, foobar', `Word was: x
     ')dnl
     ⇒Word was: foo
     ⇒Word was: bar
     ⇒Word was: foobar

It is possible to be more complex; each element of the paren-listorquote-list can itself be a list, to pass as further argumentsto a helper macro. This example generates a shell case statement:

     $ m4 -I examples
     include(`foreach.m4')
     ⇒
     define(`_case', `  $1)
         $2=" $1";;
     ')dnl
     define(`_cat', `$1$2')dnl
     case $`'1 in
     ⇒case $1 in
     foreach(`x', `(`(`a', `vara')', `(`b', `varb')', `(`c', `varc')')',
             `_cat(`_case', x)')dnl
     ⇒  a)
     ⇒    vara=" a";;
     ⇒  b)
     ⇒    varb=" b";;
     ⇒  c)
     ⇒    varc=" c";;
     esac
     ⇒esac

The implementation of the foreach macro is a bit more involved;it is a wrapper around two helper macros. First,_arg1 isneeded to grab the first element of a list. Second,_foreach implements the recursion, successively walkingthrough the original list. Here is a simple implementation offoreach:

     $ m4 -I examples
     undivert(`foreach.m4')dnl
     ⇒divert(`-1')
     ⇒# foreach(x, (item_1, item_2, ..., item_n), stmt)
     ⇒#   parenthesized list, simple version
     ⇒define(`foreach', `pushdef(`$1')_foreach($@)popdef(`$1')')
     ⇒define(`_arg1', `$1')
     ⇒define(`_foreach', `ifelse(`$2', `()', `',
     ⇒  `define(`$1', _arg1$2)$3`'$0(`$1', (shift$2), `$3')')')
     ⇒divert`'dnl

Unfortunately, that implementation is not robust to macro names as listelements. Each iteration of_foreach is stripping anotherlayer of quotes, leading to erratic results if list elements are notalready fully expanded. The first cut at implementingforeachqtakes this into account. Also, when using quoted elements in aparen-list, the overall list must be quoted. Aquote-listhas the nice property of requiring fewer characters to create a listcontaining the same quoted elements. To see the difference between thetwo macros, we attempt to pass double-quoted macro names in a list,expecting the macro name on output after one layer of quotes is removedduring list iteration and the final layer removed during the finalrescan:

     $ m4 -I examples
     define(`a', `1')define(`b', `2')define(`c', `3')
     ⇒
     include(`foreach.m4')
     ⇒
     include(`foreachq.m4')
     ⇒
     foreach(`x', `(``a'', ``(b'', ``c)'')', `x
     ')
     ⇒1
     ⇒(2)1
     ⇒
     ⇒, x
     ⇒)
     foreachq(`x', ```a'', ``(b'', ``c)''', `x
     ')dnl
     ⇒a
     ⇒(b
     ⇒c)

Obviously, foreachq did a better job; here is its implementation:

     $ m4 -I examples
     undivert(`foreachq.m4')dnl
     ⇒include(`quote.m4')dnl
     ⇒divert(`-1')
     ⇒# foreachq(x, `item_1, item_2, ..., item_n', stmt)
     ⇒#   quoted list, simple version
     ⇒define(`foreachq', `pushdef(`$1')_foreachq($@)popdef(`$1')')
     ⇒define(`_arg1', `$1')
     ⇒define(`_foreachq', `ifelse(quote($2), `', `',
     ⇒  `define(`$1', `_arg1($2)')$3`'$0(`$1', `shift($2)', `$3')')')
     ⇒divert`'dnl

Notice that _foreachq had to use the helper macroquote defined earlier (seeShift), to ensure that theembedded ifelse call does not go haywire if a list elementcontains a comma. Unfortunately, this implementation offoreachqhas its own severe flaw. Whereas the foreach implementation waslinear, this macro is quadratic in the number of list elements, and ismuch more likely to trip up the limit set by the command line option--nesting-limit (or -L, see Invoking m4). Additionally, this implementation does not expand‘defn(`iterator')’ very well, when compared withforeach.

     $ m4 -I examples
     include(`foreach.m4')include(`foreachq.m4')
     ⇒
     foreach(`name', `(`a', `b')', ` defn(`name')')
     ⇒ a b
     foreachq(`name', ``a', `b'', ` defn(`name')')
     ⇒ _arg1(`a', `b') _arg1(shift(`a', `b'))

It is possible to have robust iteration with linear behavior and saneiterator contents for either list style. See if you can learnfrom the best elements of both of these implementations to create robustmacros (or seeAnswers).


Next:  ,Previous:  Foreach,Up:  Conditionals

6.6 Working with definition stacks

Thanks topushdef, manipulation of a stack is an intrinsicoperation in m4. Normally, only the topmost definition in astack is important, but sometimes, it is desirable to manipulate theentire definition stack.

— Composite: stack_foreach ( macro, action)
— Composite: stack_foreach_lifo ( macro, action)

For each of the pushdef definitions associated with macro,invoke the macroaction with a single argument of that definition. stack_foreach visits the oldest definition first, whilestack_foreach_lifo visits the current definition first.action should not modify or dereference macro. There are afew special macros, such asdefn, which cannot be used as themacro parameter.

A sample implementation of these macros is distributed in the filem4-1.4.16/examples/stack.m4.

     $ m4 -I examples
     include(`stack.m4')
     ⇒
     pushdef(`a', `1')pushdef(`a', `2')pushdef(`a', `3')
     ⇒
     define(`show', ``$1'
     ')
     ⇒
     stack_foreach(`a', `show')dnl
     ⇒1
     ⇒2
     ⇒3
     stack_foreach_lifo(`a', `show')dnl
     ⇒3
     ⇒2
     ⇒1

Now for the implementation. Note the definition of a helper macro,_stack_reverse, which destructively swaps the contents of onestack of definitions into the reverse order in the temporary macro‘tmp-$1’. By calling the helper twice, the original order isrestored back into the macro ‘$1’; since the operation isdestructive, this explains why ‘$1’ must not be modified ordereferenced during the traversal. The caller can then injectadditional code to pass the definition currently being visited to‘$2’. The choice of helper names is intentional; since ‘-’ isnot valid as part of a macro name, there is no risk of conflict with avalid macro name, and the code is guaranteed to usedefn wherenecessary. Finally, note that any macro used in the traversal of apushdef stack, such aspushdef or defn, cannot behandled by stack_foreach, since the macro would temporarily beundefined during the algorithm.

     $ m4 -I examples
     undivert(`stack.m4')dnl
     ⇒divert(`-1')
     ⇒# stack_foreach(macro, action)
     ⇒# Invoke ACTION with a single argument of each definition
     ⇒# from the definition stack of MACRO, starting with the oldest.
     ⇒define(`stack_foreach',
     ⇒`_stack_reverse(`$1', `tmp-$1')'dnl
     ⇒`_stack_reverse(`tmp-$1', `$1', `$2(defn(`$1'))')')
     ⇒# stack_foreach_lifo(macro, action)
     ⇒# Invoke ACTION with a single argument of each definition
     ⇒# from the definition stack of MACRO, starting with the newest.
     ⇒define(`stack_foreach_lifo',
     ⇒`_stack_reverse(`$1', `tmp-$1', `$2(defn(`$1'))')'dnl
     ⇒`_stack_reverse(`tmp-$1', `$1')')
     ⇒define(`_stack_reverse',
     ⇒`ifdef(`$1', `pushdef(`$2', defn(`$1'))$3`'popdef(`$1')$0($@)')')
     ⇒divert`'dnl


Previous:  Stacks,Up:  Conditionals

6.7 Building macros with macros

Since m4 is a macro language, it is possible to write macros thatcan build other macros. First on the list is a way to automate thecreation of blind macros.

— Composite: define_blind ( name, [ value ])

Defines name as a blind macro, such that name will expand tovalue only when given explicit arguments.value should notbe the result of defn (see Defn). This macro is onlyrecognized with parameters, and results in an empty string.

Defining a macro to define another macro can be a bit tricky. We wantto use a literal ‘$#’ in the argument to the nesteddefine. However, if ‘$’ and ‘#’ are adjacent in the definition ofdefine_blind, then it would be expanded as the number ofarguments todefine_blind rather than the intended number ofarguments to name. The solution is to pass the difficultcharacters through extra arguments to a helper macro_define_blind. When composing macros, it is a common idiom toneed a helper macro to concatenate text that forms parameters in thecomposed macro, rather than interpreting the text as a parameter of thecomposing macro.

As for the limitation against using defn, there are two reasons. If a macro was previously defined withdefine_blind, then it cansafely be renamed to a new blind macro using plaindefine; usingdefine_blind to rename it just adds another layer ofifelse, occupying memory and slowing down execution. And if amacro is a builtin, then it would result in an attempt to define a macroconsisting of both text and a builtin token; this is not supported, andthe builtin token is flattened to an empty string.

With that explanation, here's the definition, and some sample usage. Notice thatdefine_blind is itself a blind macro.

     $ m4 -d
     define(`define_blind', `ifelse(`$#', `0', ``$0'',
     `_$0(`$1', `$2', `$'`#', `$'`0')')')
     ⇒
     define(`_define_blind', `define(`$1',
     `ifelse(`$3', `0', ``$4'', `$2')')')
     ⇒
     define_blind
     ⇒define_blind
     define_blind(`foo', `arguments were $*')
     ⇒
     foo
     ⇒foo
     foo(`bar')
     ⇒arguments were bar
     define(`blah', defn(`foo'))
     ⇒
     blah
     ⇒blah
     blah(`a', `b')
     ⇒arguments were a,b
     defn(`blah')
     ⇒ifelse(`$#', `0', ``$0'', `arguments were $*')

Another interesting composition tactic is argumentcurrying, orfactoring a macro that takes multiple arguments for use in a contextthat provides exactly one argument.

— Composite: curry ( macro, ...)

Expand to a macro call that takes exactly one argument, then appendsthat argument to the original arguments and invokesmacro with theresulting list of arguments.

A demonstration of currying makes the intent of this macro a little moreobvious. The macrostack_foreach mentioned earlier is an exampleof a context that provides exactly one argument to a macro name. Butcoupled with currying, we can invokereverse with two argumentsfor each definition of a macro stack. This example uses the filem4-1.4.16/examples/curry.m4 included in thedistribution.

     $ m4 -I examples
     include(`curry.m4')include(`stack.m4')
     ⇒
     define(`reverse', `ifelse(`$#', `0', , `$#', `1', ``$1'',
                               `reverse(shift($@)), `$1'')')
     ⇒
     pushdef(`a', `1')pushdef(`a', `2')pushdef(`a', `3')
     ⇒
     stack_foreach(`a', `:curry(`reverse', `4')')
     ⇒:1, 4:2, 4:3, 4
     curry(`curry', `reverse', `1')(`2')(`3')
     ⇒3, 2, 1

Now for the implementation. Notice how curry leaves off with amacro name but no open parenthesis, while still in the middle ofcollecting arguments for ‘$1’. The macro_curry is thehelper macro that takes one argument, then adds it to the list andfinally supplies the closing parenthesis. The use of a comma inside theshift call allows currying to also work for a macro that takesone argument, although it often makes more sense to invoke that macrodirectly rather than going throughcurry.

     $ m4 -I examples
     undivert(`curry.m4')dnl
     ⇒divert(`-1')
     ⇒# curry(macro, args)
     ⇒# Expand to a macro call that takes one argument, then invoke
     ⇒# macro(args, extra).
     ⇒define(`curry', `$1(shift($@,)_$0')
     ⇒define(`_curry', ``$1')')
     ⇒divert`'dnl

Unfortunately, with M4 1.4.x, curry is unable to handle builtintokens, which are silently flattened to the empty string when passedthrough another text macro. This limitation will be lifted in a futurerelease of M4.

Putting the last few concepts together, it is possible to copy or renamean entire stack of macro definitions.

— Composite: copy ( source, dest)
— Composite: rename ( source, dest)

Ensure that dest is undefined, then define it to the same stack ofdefinitions currently insource. copy leaves sourceunchanged, while rename undefines source. There are only afew macros, such as copy or defn, which cannot be copiedvia this macro.

The implementation is relatively straightforward (although since it usescurry, it is unable to copy builtin macros, such as the seconddefinition ofa as a synonym for divnum. See if you candesign a version that works around this limitation, or seeAnswers).

     $ m4 -I examples
     include(`curry.m4')include(`stack.m4')
     ⇒
     define(`rename', `copy($@)undefine(`$1')')dnl
     define(`copy', `ifdef(`$2', `errprint(`$2 already defined
     ')m4exit(`1')',
        `stack_foreach(`$1', `curry(`pushdef', `$2')')')')dnl
     pushdef(`a', `1')pushdef(`a', defn(`divnum'))pushdef(`a', `2')
     ⇒
     copy(`a', `b')
     ⇒
     rename(`b', `c')
     ⇒
     a b c
     ⇒2 b 2
     popdef(`a', `c')c a
     ⇒ 0
     popdef(`a', `c')a c
     ⇒1 1


Next:  ,Previous:  Conditionals,Up:  Top

7 How to debug macros and input

When writing macros form4, they often do not work as intended onthe first try (as is the case with most programming languages). Fortunately, there is support for macro debugging inm4.


Next:  ,Up:  Debugging

7.1 Displaying macro definitions

If you want to see what a name expands into, you can use the builtindumpdef:

— Builtin: dumpdef ( [ names... ])

Accepts any number of arguments. If called without any arguments,it displays the definitions of all known names, otherwise it displaysthe definitions of thenames given. The output is printed to thecurrent debug file (usually standard error), and is sorted by name. Ifan unknown name is encountered, a warning is printed.

The expansion of dumpdef is void.

     $ m4 -d
     define(`foo', `Hello world.')
     ⇒
     dumpdef(`foo')
     error-->foo: `Hello world.'
     ⇒
     dumpdef(`define')
     error-->define: <define>
     ⇒

The last example shows how builtin macros definitions are displayed. The definition that is dumped corresponds to what would occur if themacro were to be called at that point, even if other definitions arestill live due to redefining a macro during argument collection.

     $ m4 -d
     pushdef(`f', ``$0'1')pushdef(`f', ``$0'2')
     ⇒
     f(popdef(`f')dumpdef(`f'))
     error-->f: ``$0'1'
     ⇒f2
     f(popdef(`f')dumpdef(`f'))
     error-->m4:stdin:3: undefined macro `f'
     ⇒f1

See Debug Levels, for information on controlling the details of thedisplay.


Next:  ,Previous:  Dumpdef,Up:  Debugging

7.2 Tracing macro calls

It is possible to trace macro calls and expansions through the builtinstraceon and traceoff:

— Builtin: traceon ( [ names... ])
— Builtin: traceoff ( [ names... ])

When called without any arguments, traceon and traceoffwill turn tracing on and off, respectively, for all currently definedmacros.

When called with arguments, only the macros listed in names areaffected, whether or not they are currently defined.

The expansion of traceon and traceoff is void.

Whenever a traced macro is called and the arguments have been collected,the call is displayed. If the expansion of the macro call is not void,the expansion can be displayed after the call. The output is printedto the current debug file (defaulting to standard error, see Debug Output).

     $ m4 -d
     define(`foo', `Hello World.')
     ⇒
     define(`echo', `$@')
     ⇒
     traceon(`foo', `echo')
     ⇒
     foo
     error-->m4trace: -1- foo -> `Hello World.'
     ⇒Hello World.
     echo(`gnus', `and gnats')
     error-->m4trace: -1- echo(`gnus', `and gnats') -> ``gnus',`and gnats''
     ⇒gnus,and gnats

The number between dashes is the depth of the expansion. It is one mostof the time, signifying an expansion at the outermost level, but itincreases when macro arguments contain unquoted macro calls. Themaximum number that will appear between dashes is controlled by theoption --nesting-limit (or -L, see Invoking m4). Additionally, the option--trace (or-t) can be used to invoketraceon(name) beforeparsing input.

     $ m4 -L 3 -t ifelse
     ifelse(`one level')
     error-->m4trace: -1- ifelse
     ⇒
     ifelse(ifelse(ifelse(`three levels')))
     error-->m4trace: -3- ifelse
     error-->m4trace: -2- ifelse
     error-->m4trace: -1- ifelse
     ⇒
     ifelse(ifelse(ifelse(ifelse(`four levels'))))
     error-->m4:stdin:3: recursion limit of 3 exceeded, use -L<N> to change it

Tracing by name is an attribute that is preserved whether the macro isdefined or not. This allows the selection of macros to trace beforethose macros are defined.

     $ m4 -d
     traceoff(`foo')
     ⇒
     traceon(`foo')
     ⇒
     foo
     ⇒foo
     defn(`foo')
     ⇒
     define(`foo', `bar')
     ⇒
     foo
     error-->m4trace: -1- foo -> `bar'
     ⇒bar
     undefine(`foo')
     ⇒
     ifdef(`foo', `yes', `no')
     ⇒no
     indir(`foo')
     error-->m4:stdin:9: undefined macro `foo'
     ⇒
     define(`foo', `blah')
     ⇒
     foo
     error-->m4trace: -1- foo -> `blah'
     ⇒blah
     traceoff
     ⇒
     foo
     ⇒blah

Tracing even works on builtins. However, defn (see Defn)does not transfer tracing status.

     $ m4 -d
     traceon(`traceon')
     ⇒
     traceon(`traceoff')
     error-->m4trace: -1- traceon(`traceoff')
     ⇒
     traceoff(`traceoff')
     error-->m4trace: -1- traceoff(`traceoff')
     ⇒
     traceoff(`traceon')
     ⇒
     traceon(`eval', `m4_divnum')
     ⇒
     define(`m4_eval', defn(`eval'))
     ⇒
     define(`m4_divnum', defn(`divnum'))
     ⇒
     eval(divnum)
     error-->m4trace: -1- eval(`0') -> `0'
     ⇒0
     m4_eval(m4_divnum)
     error-->m4trace: -2- m4_divnum -> `0'
     ⇒0

See Debug Levels, for information on controlling the details of thedisplay. The format of the trace output is not specified byPOSIX, and varies between implementations ofm4.


Next:  ,Previous:  Trace,Up:  Debugging

7.3 Controlling debugging output

The-d option to m4 (or --debug,seeInvoking m4) controls the amount of detailspresented in threecategories of output. Trace output is requested bytraceon(see Trace), and each line is prefixed by ‘m4trace:’ inrelation to a macro invocation. Debug output tracks useful events notassociated with a macro invocation, and each line is prefixed by‘m4debug:’. Finally, dumpdef (seeDumpdef) output isaffected, with no prefix added to the output lines.

The flags following the option can be one or more of thefollowing:

a
In trace output, show the actual arguments that were collected beforeinvoking the macro. This applies to all macro calls if the ‘ t’flag is used, otherwise only the macros covered by calls of traceon. Arguments are subject to length truncation specified bythe command line option --arglength (or -l).
c
In trace output, show several trace lines for each macro call. A lineis shown when the macro is seen, but before the arguments are collected;a second line when the arguments have been collected and a third lineafter the call has completed.
e
In trace output, show the expansion of each macro call, if it is notvoid. This applies to all macro calls if the ‘ t’ flag is used,otherwise only the macros covered by calls of traceon. Theexpansion is subject to length truncation specified by the command lineoption --arglength (or -l).
f
In debug and trace output, include the name of the current input file inthe output line.
i
In debug output, print a message each time the current input file ischanged.
l
In debug and trace output, include the current input line number in theoutput line.
p
In debug output, print a message when a named file is found through thepath search mechanism (see Search Path), giving the actual file nameused.
q
In trace and dumpdef output, quote actual arguments and macro expansionsin the display with the current quotes. This is useful in connectionwith the ‘ a’ and ‘ e’ flags above.
t
In trace output, trace all macro calls made in this invocation of m4, regardless of the settings of traceon.
x
In trace output, add a unique `macro call id' to each line of the traceoutput. This is useful in connection with the ‘ c’ flag above.
V
A shorthand for all of the above flags.

If no flags are specified with the -d option, the default is‘aeq’. The examples throughout this manual assume the defaultflags.

There is a builtin macro debugmode, which allows on-the-fly control ofthe debugging output format:

— Builtin: debugmode ( [ flags ])

The argument flags should be a subset of the letters listed above. As special cases, if the argument starts with a ‘+’, the flags areadded to the current debug flags, and if it starts with a ‘-’, theyare removed. If no argument is present, all debugging flags are cleared(as if no-d was given), and with an empty argument the flagsare reset to the default of ‘aeq’.

The expansion of debugmode is void.

     $ m4
     define(`foo', `FOO')
     ⇒
     traceon(`foo')
     ⇒
     debugmode()
     ⇒
     foo
     error-->m4trace: -1- foo -> `FOO'
     ⇒FOO
     debugmode
     ⇒
     foo
     error-->m4trace: -1- foo
     ⇒FOO
     debugmode(`+l')
     ⇒
     foo
     error-->m4trace:8: -1- foo
     ⇒FOO

The following example demonstrates the behavior of length truncation,when specified on the command line. Note that each argument and thefinal result are individually truncated. Also, the special tokens forbuiltin functions are not truncated.

     $ m4 -d -l 6
     define(`echo', `$@')debugmode(`+t')
     ⇒
     echo(`1', `long string')
     error-->m4trace: -1- echo(`1', `long s...') -> ``1',`l...'
     ⇒1,long string
     indir(`echo', defn(`changequote'))
     error-->m4trace: -2- defn(`change...')
     error-->m4trace: -1- indir(`echo', <changequote>) -> ``''
     ⇒

This example shows the effects of the debug flags that are not relatedto macro tracing.

     $ m4 -dip -I examples
     error-->m4debug: input read from stdin
     include(`foo')dnl
     error-->m4debug: path search for `foo' found `examples/foo'
     error-->m4debug: input read from examples/foo
     ⇒bar
     error-->m4debug: input reverted to stdin, line 1
     ^D
     error-->m4debug: input exhausted


Previous:  Debug Levels,Up:  Debugging

7.4 Saving debugging output

Debug and tracing output can be redirected to files using either the--debugfile option to m4 (seeInvoking m4), or with the builtin macro debugfile:

— Builtin: debugfile ( [ file ])

Sends all further debug and trace output to file, opened in appendmode. Iffile is the empty string, debug and trace output arediscarded. If debugfile is called without any arguments, debugand trace output are sent to standard error. This does not affectwarnings, error messages, orerrprint output, which arealways sent to standard error. If file cannot be opened, thecurrent debug file is unchanged, and an error is issued.

The expansion of debugfile is void.

     $ m4 -d
     traceon(`divnum')
     ⇒
     divnum(`extra')
     error-->m4:stdin:2: Warning: excess arguments to builtin `divnum' ignored
     error-->m4trace: -1- divnum(`extra') -> `0'
     ⇒0
     debugfile()
     ⇒
     divnum(`extra')
     error-->m4:stdin:4: Warning: excess arguments to builtin `divnum' ignored
     ⇒0
     debugfile
     ⇒
     divnum
     error-->m4trace: -1- divnum -> `0'
     ⇒0


Next:  ,Previous:  Debugging,Up:  Top

8 Input control

This chapter describes various builtin macros for controlling the inputto m4.


Next:  ,Up:  Input Control

8.1 Deleting whitespace in input

The builtindnl stands for “Discard to Next Line”:

— Builtin: dnl

All characters, up to and including the next newline, are discardedwithout performing any macro expansion. A warning is issued if the endof the file is encountered without a newline.

The expansion of dnl is void.

It is often used in connection with define, to remove thenewline that follows the call todefine. Thus

     define(`foo', `Macro `foo'.')dnl A very simple macro, indeed.
     foo
     ⇒Macro foo.

The input up to and including the next newline is discarded, as opposedto the way comments are treated (seeComments).

Usually, dnl is immediately followed by an end of line or someother whitespace. GNUm4 will produce a warning diagnostic ifdnl is followed by an open parenthesis. In this case,dnlwill collect and process all arguments, looking for a matching closeparenthesis. All predictable side effects resulting from thiscollection will take place.dnl will return no output. Theinput following the matching close parenthesis up to and including thenext newline, on whatever line containing it, will still be discarded.

     dnl(`args are ignored, but side effects occur',
     define(`foo', `like this')) while this text is ignored: undefine(`foo')
     error-->m4:stdin:1: Warning: excess arguments to builtin `dnl' ignored
     See how `foo' was defined, foo?
     ⇒See how foo was defined, like this?

If the end of file is encountered without a newline character, awarning is issued and dnl stops consuming input.

     m4wrap(`m4wrap(`2 hi
     ')0 hi dnl 1 hi')
     ⇒
     define(`hi', `HI')
     ⇒
     ^D
     error-->m4:stdin:1: Warning: end of file treated as newline
     ⇒0 HI 2 HI


Next:  ,Previous:  Dnl,Up:  Input Control

8.2 Changing the quote characters

The default quote delimiters can be changed with the builtinchangequote:

— Builtin: changequote ( [ start = ‘ ` ] , [ end = ‘ ' ])

This sets start as the new begin-quote delimiter and end asthe new end-quote delimiter. If both arguments are missing, the defaultquotes (` and') are used. If start is void, thenquoting is disabled. Otherwise, ifend is missing or void, thedefault end-quote delimiter (') is used. The quote delimiterscan be of any length.

The expansion of changequote is void.

     changequote(`[', `]')
     ⇒
     define([foo], [Macro [foo].])
     ⇒
     foo
     ⇒Macro foo.

The quotation strings can safely contain eight-bit characters. If no single character is appropriate,start and end can beof any length. Other implementations cap the delimiter length to fivecharacters, but GNU has no inherent limit.

     changequote(`[[[', `]]]')
     ⇒
     define([[[foo]]], [[[Macro [[[[[foo]]]]].]]])
     ⇒
     foo
     ⇒Macro [[foo]].

Calling changequote with start as the empty string willeffectively disable the quoting mechanism, leaving no way to quote text. However, using an empty string is not portable, as some otherimplementations ofm4 revert to the default quoting, while otherspreserve the prior non-empty delimiter. Ifstart is not empty,then an empty end will use the default end-quote delimiter of‘'’, as otherwise, it would be impossible to end a quoted string. Again, this is not portable, as some otherm4 implementationsreuse start as the end-quote delimiter, while others preserve theprevious non-empty value. Omitting both arguments restores the defaultbegin-quote and end-quote delimiters; fortunately this behavior isportable to all implementations of m4.

     define(`foo', `Macro `FOO'.')
     ⇒
     changequote(`', `')
     ⇒
     foo
     ⇒Macro `FOO'.
     `foo'
     ⇒`Macro `FOO'.'
     changequote(`,)
     ⇒
     foo
     ⇒Macro FOO.

There is no way in m4 to quote a string containing an unmatchedbegin-quote, except usingchangequote to change the currentquotes.

If the quotes should be changed from, say, ‘[’ to ‘[[’,temporary quote characters have to be defined. To achieve this, twocalls ofchangequote must be made, one for the temporary quotesand one for the new quotes.

Macros are recognized in preference to the begin-quote string, so if aprefix ofstart can be recognized as part of a potential macroname, the quoting mechanism is effectively disabled. Unless you usechangeword (seeChangeword), this means that startshould not begin with a letter, digit, or ‘_’ (underscore). However, even though quoted strings are not recognized, the quotecharacters can still be discerned in macro expansion and in traceoutput.

     define(`echo', `$@')
     ⇒
     define(`hi', `HI')
     ⇒
     changequote(`q', `Q')
     ⇒
     q hi Q hi
     ⇒q HI Q HI
     echo(hi)
     ⇒qHIQ
     changequote
     ⇒
     changequote(`-', `EOF')
     ⇒
     - hi EOF hi
     ⇒ hi  HI
     changequote
     ⇒
     changequote(`1', `2')
     ⇒
     hi1hi2
     ⇒hi1hi2
     hi 1hi2
     ⇒HI hi

Quotes are recognized in preference to argument collection. Inparticular, if start is a single ‘(’, then argumentcollection is effectively disabled. For portability with otherimplementations, it is a good idea to avoid ‘(’, ‘,’, and‘)’ as the first character in start.

     define(`echo', `$#:$@:')
     ⇒
     define(`hi', `HI')
     ⇒
     changequote(`(',`)')
     ⇒
     echo(hi)
     ⇒0::hi
     changequote
     ⇒
     changequote(`((', `))')
     ⇒
     echo(hi)
     ⇒1:HI:
     echo((hi))
     ⇒0::hi
     changequote
     ⇒
     changequote(`,', `)')
     ⇒
     echo(hi,hi)bye)
     ⇒1:HIhibye:

However, if you are not worried about portability, using ‘(’ and‘)’ as quoting characters has an interesting property—you can useit to compute a quoted string containing the expansion of any quotedtext, as long as the expansion results in both balanced quotes andbalanced parentheses. The trick is realizingexpand uses‘$1’ unquoted, to trigger its expansion using the normal quotingcharacters, but uses extra parentheses to group unquoted commas thatoccur in the expansion without consuming whitespace following thosecommas. Then _expand uses changequote to convert theextra parentheses back into quoting characters. Note that it takes twomorechangequote invocations to restore the original quotes. Contrast the behavior on whitespace when using ‘$*’, viaquote, to attempt the same task.

     changequote(`[', `]')dnl
     define([a], [1, (b)])dnl
     define([b], [2])dnl
     define([quote], [[$*]])dnl
     define([expand], [_$0(($1))])dnl
     define([_expand],
       [changequote([(], [)])$1changequote`'changequote(`[', `]')])dnl
     expand([a, a, [a, a], [[a, a]]])
     ⇒1, (2), 1, (2), a, a, [a, a]
     quote(a, a, [a, a], [[a, a]])
     ⇒1,(2),1,(2),a, a,[a, a]

If end is a prefix of start, the end-quote will berecognized in preference to a nested begin-quote. In particular,changing the quotes to have the same string forstart andend disables nesting of quotes. When quote nesting is disabled,it is impossible to double-quote strings across macro expansions, sousing the same string is not done very often.

     define(`hi', `HI')
     ⇒
     changequote(`""', `"')
     ⇒
     ""hi"""hi"
     ⇒hihi
     ""hi" ""hi"
     ⇒hi hi
     ""hi"" "hi"
     ⇒hi" "HI"
     changequote
     ⇒
     `hi`hi'hi'
     ⇒hi`hi'hi
     changequote(`"', `"')
     ⇒
     "hi"hi"hi"
     ⇒hiHIhi

It is an error if the end of file occurs within a quoted string.

     `hello world'
     ⇒hello world
     `dangling quote
     ^D
     error-->m4:stdin:2: ERROR: end of file in string
     ifelse(`dangling quote
     ^D
     error-->m4:stdin:1: ERROR: end of file in string


Next:  ,Previous:  Changequote,Up:  Input Control

8.3 Changing the comment delimiters

The default comment delimiters can be changed with the builtinmacrochangecom:

— Builtin: changecom ( [ start ] , [ end = ‘ <NL> ])

This sets start as the new begin-comment delimiter and endas the new end-comment delimiter. If both arguments are missing, orstart is void, then comments are disabled. Otherwise, ifend is missing or void, the default end-comment delimiter ofnewline is used. The comment delimiters can be of any length.

The expansion of changecom is void.

     define(`comment', `COMMENT')
     ⇒
     # A normal comment
     ⇒# A normal comment
     changecom(`/*', `*/')
     ⇒
     # Not a comment anymore
     ⇒# Not a COMMENT anymore
     But: /* this is a comment now */ while this is not a comment
     ⇒But: /* this is a comment now */ while this is not a COMMENT

Note how comments are copied to the output, much as if they were quotedstrings. If you want the text inside a comment expanded, quote thebegin-comment delimiter.

Calling changecom without any arguments, or with start asthe empty string, will effectively disable the commenting mechanism. Torestore the original comment start of ‘#’, you must explicitly askfor it. If start is not empty, then an empty end will usethe default end-comment delimiter of newline, as otherwise, it would beimpossible to end a comment. However, this is not portable, as someotherm4 implementations preserve the previous non-emptydelimiters instead.

     define(`comment', `COMMENT')
     ⇒
     changecom
     ⇒
     # Not a comment anymore
     ⇒# Not a COMMENT anymore
     changecom(`#', `')
     ⇒
     # comment again
     ⇒# comment again

The comment strings can safely contain eight-bit characters. If no single character is appropriate,start and end can beof any length. Other implementations cap the delimiter length to fivecharacters, but GNU has no inherent limit.

Comments are recognized in preference to macros. However, this is notcompatible with other implementations, where macros and even quotingtakes precedence over comments, so it may change in a future release. For portability, this means thatstart should not begin with aletter, digit, or ‘_’ (underscore), and that neither thestart-quote nor the start-comment string should be a prefix of theother.

     define(`hi', `HI')
     ⇒
     define(`hi1hi2', `hello')
     ⇒
     changecom(`q', `Q')
     ⇒
     q hi Q hi
     ⇒q hi Q HI
     changecom(`1', `2')
     ⇒
     hi1hi2
     ⇒hello
     hi 1hi2
     ⇒HI 1hi2

Comments are recognized in preference to argument collection. Inparticular, ifstart is a single ‘(’, then argumentcollection is effectively disabled. For portability with otherimplementations, it is a good idea to avoid ‘(’, ‘,’, and‘)’ as the first character in start.

     define(`echo', `$#:$*:$@:')
     ⇒
     define(`hi', `HI')
     ⇒
     changecom(`(',`)')
     ⇒
     echo(hi)
     ⇒0:::(hi)
     changecom
     ⇒
     changecom(`((', `))')
     ⇒
     echo(hi)
     ⇒1:HI:HI:
     echo((hi))
     ⇒0:::((hi))
     changecom(`,', `)')
     ⇒
     echo(hi,hi)bye)
     ⇒1:HI,hi)bye:HI,hi)bye:
     changecom
     ⇒
     echo(hi,`,`'hi',hi)
     ⇒3:HI,,HI,HI:HI,,`'hi,HI:
     echo(hi,`,`'hi',hi`'changecom(`,,', `hi'))
     ⇒3:HI,,`'hi,HI:HI,,`'hi,HI:

It is an error if the end of file occurs within a comment.

     changecom(`/*', `*/')
     ⇒
     /*dangling comment
     ^D
     error-->m4:stdin:2: ERROR: end of file in comment


Next:  ,Previous:  Changecom,Up:  Input Control

8.4 Changing the lexical structure of words

The macro changeword and all associated functionality isexperimental. It is only available if the --enable-changewordoption was given to configure, at GNU m4installationtime. The functionality will go away in the future, to be replaced byother new features that are more efficient at providing the samecapabilities. Do not rely on it. Please direct your commentsabout it the same way you would do for bugs.

A file being processed by m4 is split into quoted strings, words(potential macro names) and simple tokens (any other single character). Initially a word is defined by the following regular expression:

     [_a-zA-Z][_a-zA-Z0-9]*

Using changeword, you can change this regular expression:

— Optional builtin: changeword ( regex)

Changes the regular expression for recognizing macro names to beregex. Ifregex is empty, use‘[_a-zA-Z][_a-zA-Z0-9]*’.regex must obey the constraintthat every prefix of the desired final pattern is also accepted by theregular expression. Ifregex contains grouping parentheses, themacro invoked is the portion that matched the first group, rather thanthe entire matching string.

The expansion of changeword is void. The macro changeword is recognized only with parameters.

Relaxing the lexical rules of m4 might be useful (for example) ifyou wanted to apply translations to a file of numbers:

     ifdef(`changeword', `', `errprint(` skipping: no changeword support
     ')m4exit(`77')')dnl
     changeword(`[_a-zA-Z0-9]+')
     ⇒
     define(`1', `0')1
     ⇒0

Tightening the lexical rules is less useful, because it will generallymake some of the builtins unavailable. You could use it to preventaccidental call of builtins, for example:

     ifdef(`changeword', `', `errprint(` skipping: no changeword support
     ')m4exit(`77')')dnl
     define(`_indir', defn(`indir'))
     ⇒
     changeword(`_[_a-zA-Z0-9]*')
     ⇒
     esyscmd(`foo')
     ⇒esyscmd(foo)
     _indir(`esyscmd', `echo hi')
     ⇒hi
     ⇒

Because m4 constructs its words a character at a time, thereis a restriction on the regular expressions that may be passed tochangeword. This is that if your regular expression accepts‘foo’, it must also accept ‘f’ and ‘fo’.

     ifdef(`changeword', `', `errprint(` skipping: no changeword support
     ')m4exit(`77')')dnl
     define(`foo
     ', `bar
     ')
     ⇒
     dnl This example wants to recognize changeword, dnl, and `foo\n'.
     dnl First, we check that our regexp will match.
     regexp(`changeword', `[cd][a-z]*\|foo[
     ]')
     ⇒0
     regexp(`foo
     ', `[cd][a-z]*\|foo[
     ]')
     ⇒0
     regexp(`f', `[cd][a-z]*\|foo[
     ]')
     ⇒-1
     foo
     ⇒foo
     changeword(`[cd][a-z]*\|foo[
     ]')
     ⇒
     dnl Even though `foo\n' matches, we forgot to allow `f'.
     foo
     ⇒foo
     changeword(`[cd][a-z]*\|fo*[
     ]?')
     ⇒
     dnl Now we can call `foo\n'.
     foo
     ⇒bar

changeword has another function. If the regular expressionsupplied contains any grouped subexpressions, then text outsidethe first of these is discarded before symbol lookup. So:

     ifdef(`changeword', `', `errprint(` skipping: no changeword support
     ')m4exit(`77')')dnl
     ifdef(`__unix__', ,
           `errprint(` skipping: syscmd does not have unix semantics
     ')m4exit(`77')')dnl
     changecom(`/*', `*/')dnl
     define(`foo', `bar')dnl
     changeword(`#\([_a-zA-Z0-9]*\)')
     ⇒
     #esyscmd(`echo foo \#foo')
     ⇒foo bar
     ⇒

m4 now requires a ‘#’ mark at the beginning of everymacro invocation, so one can usem4 to preprocess plaintext without losing various words like ‘divert’.

In m4, macro substitution is based on text, while in TeX, itis based on tokens.changeword can throw this difference intorelief. For example, here is the same idea represented in TeX andm4. First, the TeX version:

     \def\a{\message{Hello}}
     \catcode`\@=0
     \catcode`\\=12
     @a
     @bye
     ⇒Hello

Then, the m4 version:

     ifdef(`changeword', `', `errprint(` skipping: no changeword support
     ')m4exit(`77')')dnl
     define(`a', `errprint(`Hello')')dnl
     changeword(`@\([_a-zA-Z0-9]*\)')
     ⇒
     @a
     ⇒errprint(Hello)

In the TeX example, the first line defines a macro a toprint the message ‘Hello’. The second line defines <@> tobe usable instead of <\> as an escape character. The third linedefines <\> to be a normal printing character, not an escape. The fourth line invokes the macro a. So, when TeX is runon this file, it displays the message ‘Hello’.

When the m4 example is passed through m4, it outputs‘errprint(Hello)’. The reason for this is that TeX doeslexical analysis of macro definition when the macro isdefined. m4 just stores the text, postponing the lexical analysis untilthe macro isused.

You should note that using changeword will slow m4 downby a factor of about seven, once it is changed to something otherthan the default regular expression. You can invokechangewordwith the empty string to restore the default word definition, and regainthe parsing speed.


Previous:  Changeword,Up:  Input Control

8.5 Saving text until end of input

It is possible to `save' some text until the end of the normal input hasbeen seen. Text can be saved, to be read again by m4 when thenormal input has been exhausted. This feature is normally used toinitiate cleanup actions before normal exit, e.g., deleting temporaryfiles.

To save input text, use the builtin m4wrap:

— Builtin: m4wrap ( string, ...)

Stores string in a safe place, to be reread when end of input isreached. As a GNU extension, additional arguments areconcatenated with a space to thestring.

The expansion of m4wrap is void. The macro m4wrap is recognized only with parameters.

     define(`cleanup', `This is the `cleanup' action.
     ')
     ⇒
     m4wrap(`cleanup')
     ⇒
     This is the first and last normal input line.
     ⇒This is the first and last normal input line.
     ^D
     ⇒This is the cleanup action.

The saved input is only reread when the end of normal input is seen, andnot ifm4exit is used to exit m4.

It is safe to call m4wrap from saved text, but then the order inwhich the saved text is reread is undefined. Ifm4wrap is not usedrecursively, the saved pieces of text are reread in the opposite orderin which they were saved (LIFO—last in, first out). However, thisbehavior is likely to change in a future release, to matchPOSIX, so you should not depend on this order.

It is possible to emulate POSIX behavior evenwith older versions of GNU M4 by including the filem4-1.4.16/examples/wrapfifo.m4 from thedistribution:

     $ m4 -I examples
     undivert(`wrapfifo.m4')dnl
     ⇒dnl Redefine m4wrap to have FIFO semantics.
     ⇒define(`_m4wrap_level', `0')dnl
     ⇒define(`m4wrap',
     ⇒`ifdef(`m4wrap'_m4wrap_level,
     ⇒       `define(`m4wrap'_m4wrap_level,
     ⇒               defn(`m4wrap'_m4wrap_level)`$1')',
     ⇒       `builtin(`m4wrap', `define(`_m4wrap_level',
     ⇒                                  incr(_m4wrap_level))dnl
     ⇒m4wrap'_m4wrap_level)dnl
     ⇒define(`m4wrap'_m4wrap_level, `$1')')')dnl
     include(`wrapfifo.m4')
     ⇒
     m4wrap(`a`'m4wrap(`c
     ', `d')')m4wrap(`b')
     ⇒
     ^D
     ⇒abc

It is likewise possible to emulate LIFO behavior without resorting tothe GNU M4 extension ofbuiltin, by including the filem4-1.4.16/examples/wraplifo.m4 from thedistribution. (Unfortunately, both examples shown here share somesubtle bugs. See if you can find and correct them; or seeAnswers).

     $ m4 -I examples
     undivert(`wraplifo.m4')dnl
     ⇒dnl Redefine m4wrap to have LIFO semantics.
     ⇒define(`_m4wrap_level', `0')dnl
     ⇒define(`_m4wrap', defn(`m4wrap'))dnl
     ⇒define(`m4wrap',
     ⇒`ifdef(`m4wrap'_m4wrap_level,
     ⇒       `define(`m4wrap'_m4wrap_level,
     ⇒               `$1'defn(`m4wrap'_m4wrap_level))',
     ⇒       `_m4wrap(`define(`_m4wrap_level', incr(_m4wrap_level))dnl
     ⇒m4wrap'_m4wrap_level)dnl
     ⇒define(`m4wrap'_m4wrap_level, `$1')')')dnl
     include(`wraplifo.m4')
     ⇒
     m4wrap(`a`'m4wrap(`c
     ', `d')')m4wrap(`b')
     ⇒
     ^D
     ⇒bac

Here is an example of implementing a factorial function usingm4wrap:

     define(`f', `ifelse(`$1', `0', `Answer: 0!=1
     ', eval(`$1>1'), `0', `Answer: $2$1=eval(`$2$1')
     ', `m4wrap(`f(decr(`$1'), `$2$1*')')')')
     ⇒
     f(`10')
     ⇒
     ^D
     ⇒Answer: 10*9*8*7*6*5*4*3*2*1=3628800

Invocations of m4wrap at the same recursion level areconcatenated and rescanned as usual:

     define(`aa', `AA
     ')
     ⇒
     m4wrap(`a')m4wrap(`a')
     ⇒
     ^D
     ⇒AA

however, the transition between recursion levels behaves like an end offile condition between two input files.

     m4wrap(`m4wrap(`)')len(abc')
     ⇒
     ^D
     error-->m4:stdin:1: ERROR: end of file in argument list


Next:  ,Previous:  Input Control,Up:  Top

9 File inclusion

m4 allows you to include named files at any point in the input.


Next:  ,Up:  File Inclusion

9.1 Including named files

There are two builtin macros in m4 for including files:

— Builtin: include ( file)
— Builtin: sinclude ( file)

Both macros cause the file named file to be read bym4. When the end of the file is reached, input is resumed fromthe previous input file.

The expansion of include and sinclude is therefore thecontents offile.

If file does not exist, is a directory, or cannot otherwise beread, the expansion is void,andinclude will fail with an error while sinclude issilent. The empty string counts as a file that does not exist.

The macros include and sinclude are recognized only withparameters.

     include(`none')
     error-->m4:stdin:1: cannot open `none': No such file or directory
     ⇒
     include()
     error-->m4:stdin:2: cannot open `': No such file or directory
     ⇒
     sinclude(`none')
     ⇒
     sinclude()
     ⇒

The rest of this section assumes that m4 is invoked with the-I option (seeInvoking m4)pointing to the m4-1.4.16/examplesdirectory shipped as part of the GNUm4 package. Thefile m4-1.4.16/examples/incl.m4 in the distributioncontains the lines:

     $ cat examples/incl.m4
     ⇒Include file start
     ⇒foo
     ⇒Include file end

Normally file inclusion is used to insert the contents of a fileinto the input stream. The contents of the file will be read bym4 and macro calls in the file will be expanded:

     $ m4 -I examples
     define(`foo', `FOO')
     ⇒
     include(`incl.m4')
     ⇒Include file start
     ⇒FOO
     ⇒Include file end
     ⇒

The fact that include and sinclude expand to the contentsof the file can be used to define macros that operate on entire files. Here is an example, which defines ‘bar’ to expand to the contentsofincl.m4:

     $ m4 -I examples
     define(`bar', include(`incl.m4'))
     ⇒
     This is `bar':  >>bar<<
     ⇒This is bar:  >>Include file start
     ⇒foo
     ⇒Include file end
     ⇒<<

This use of include is not trivial, though, as files can containquotes, commas, and parentheses, which can interfere with the way them4 parser works. GNUm4 seamlessly concatenatesthe file contents with the next character, even if the included fileended in the middle of a comment, string, or macro call. Theseconditions are only treated as end of file errors if specified as inputfiles on the command line.

In GNU m4, an alternative method of reading files isusing undivert (seeUndivert) on a named file.


Previous:  Include,Up:  File Inclusion

9.2 Searching for include files

GNUm4 allows included files to be found in other directoriesthan the current working directory.

If the --prepend-include or-B command-line option wasprovided (see Invoking m4), thosedirectories are searched first, in reverse order that those options werelisted on the command line. Thenm4 looks in the current workingdirectory. Next comes the directories specified with the--include or-I option, in the order found on thecommand line. Finally, if theM4PATH environment variable is set,it is expected to contain a colon-separated list of directories, whichwill be searched in order.

If the automatic search for include-files causes trouble, the ‘p’debug flag (seeDebug Levels) can help isolate the problem.


Next:  ,Previous:  File Inclusion,Up:  Top

10 Diverting and undiverting output

Diversions are a way of temporarily saving output. The output ofm4 can at any time be diverted to a temporary file, and bereinserted into the output stream,undiverted, again at a latertime.

Numbered diversions are counted from 0 upwards, diversion number 0being the normal output stream. GNUm4 tries to keep diversions in memory. However, there is alimit to the overall memory usable by all diversions taken together(512K, currently). When this maximum is about to be exceeded,a temporary file is opened to receive the contents of the biggestdiversion still in memory, freeing this memory for other diversions. When creating the temporary file,m4 honors the value of theenvironment variable TMPDIR, and falls back to/tmp. Thus, the amount of available disk space provides the only real limit onthe number and aggregate size of diversions.

Diversions make it possible to generate output in a different order thanthe input was read. It is possible to implement topological sortingdependencies. For example, GNU Autoconf makes use ofdiversions under the hood to ensure that the expansion of a prerequisitemacro appears in the output prior to the expansion of a dependent macro,regardless of which order the two macros were invoked in the user'sinput file.


Next:  ,Up:  Diversions

10.1 Diverting output

Output is diverted usingdivert:

— Builtin: divert ( [ number = ‘ 0 ])

The current diversion is changed to number. If number is leftout or empty, it is assumed to be zero. Ifnumber cannot beparsed, the diversion is unchanged.

The expansion of divert is void.

When all the m4 input will have been processed, all existingdiversions are automatically undiverted, in numerical order.

     divert(`1')
     This text is diverted.
     divert
     ⇒
     This text is not diverted.
     ⇒This text is not diverted.
     ^D
     ⇒
     ⇒This text is diverted.

Several calls of divert with the same argument do not overwritethe previous diverted text, but append to it. Diversions are printedafter any wrapped text is expanded.

     define(`text', `TEXT')
     ⇒
     divert(`1')`diverted text.'
     divert
     ⇒
     m4wrap(`Wrapped text precedes ')
     ⇒
     ^D
     ⇒Wrapped TEXT precedes diverted text.

If output is diverted to a negative diversion, it is simply discarded. This can be used to suppress unwanted output. A common example ofunwanted output is the trailing newlines after macro definitions. Hereis a common programming idiom in m4 for avoiding them.

     divert(`-1')
     define(`foo', `Macro `foo'.')
     define(`bar', `Macro `bar'.')
     divert
     ⇒

Traditional implementations only supported ten diversions. But as aGNU extension, diversion numbers can be as large as positiveintegers will allow, rather than treating a multi-digit diversion numberas a request to discard text.

     divert(eval(`1<<28'))world
     divert(`2')hello
     ^D
     ⇒hello
     ⇒world

Note that divert is an English word, but also an active macrowithout arguments. When processing plain text, the word might appear innormal text and be unintentionally swallowed as a macro invocation. Oneway to avoid this is to use the-P option to rename allbuiltins (see Invoking m4). Another is to writea wrapper that requires a parameter to be recognized.

     We decided to divert the stream for irrigation.
     ⇒We decided to  the stream for irrigation.
     define(`divert', `ifelse(`$#', `0', ``$0'', `builtin(`$0', $@)')')
     ⇒
     divert(`-1')
     Ignored text.
     divert(`0')
     ⇒
     We decided to divert the stream for irrigation.
     ⇒We decided to divert the stream for irrigation.


Next:  ,Previous:  Divert,Up:  Diversions

10.2 Undiverting output

Diverted text can be undiverted explicitly using the builtinundivert:

— Builtin: undivert ( [ diversions... ])

Undiverts the numeric diversions given by the arguments, in theorder given. If no arguments are supplied, all diversions areundiverted, in numerical order.

As a GNU extension,diversions may contain non-numericstrings, which are treated as the names of files to copy into the outputwithout expansion. A warning is issued if a file could not be opened.

The expansion of undivert is void.

     divert(`1')
     This text is diverted.
     divert
     ⇒
     This text is not diverted.
     ⇒This text is not diverted.
     undivert(`1')
     ⇒
     ⇒This text is diverted.
     ⇒

Notice the last two blank lines. One of them comes from the newlinefollowing undivert, the other from the newline that followed thedivert! A diversion often starts with a blank line like this.

When diverted text is undiverted, it is not reread by m4,but rather copied directly to the current output, and it is thereforenot an error to undivert into a diversion. Undiverting the empty stringis the same as specifying diversion 0; in either case nothing happenssince the output has already been flushed.

     divert(`1')diverted text
     divert
     ⇒
     undivert()
     ⇒
     undivert(`0')
     ⇒
     undivert
     ⇒diverted text
     ⇒
     divert(`1')more
     divert(`2')undivert(`1')diverted text`'divert
     ⇒
     undivert(`1')
     ⇒
     undivert(`2')
     ⇒more
     ⇒diverted text

When a diversion has been undiverted, the diverted text is discarded,and it is not possible to bring back diverted text more than once.

     divert(`1')
     This text is diverted first.
     divert(`0')undivert(`1')dnl
     ⇒
     ⇒This text is diverted first.
     undivert(`1')
     ⇒
     divert(`1')
     This text is also diverted but not appended.
     divert(`0')undivert(`1')dnl
     ⇒
     ⇒This text is also diverted but not appended.

Attempts to undivert the current diversion are silently ignored. Thus,when the current diversion is not 0, the current diversion does not getrearranged among the other diversions.

     divert(`1')one
     divert(`2')two
     divert(`3')three
     divert(`2')undivert`'dnl
     divert`'undivert`'dnl
     ⇒two
     ⇒one
     ⇒three

GNUm4 allows named files to be undiverted. Given anon-numeric argument, the contents of the file named will be copied,uninterpreted, to the current output. This complements the builtininclude (seeInclude). To illustrate the difference, assumethe file foo contains:

     $ cat foo
     bar

then

     define(`bar', `BAR')
     ⇒
     undivert(`foo')
     ⇒bar
     ⇒
     include(`foo')
     ⇒BAR
     ⇒

If the file is not found (or cannot be read), an error message isissued, and the expansion is void. It is possible to intermix filesand diversion numbers.

     divert(`1')diversion one
     divert(`2')undivert(`foo')dnl
     divert(`3')diversion three
     divert`'dnl
     undivert(`1', `2', `foo', `3')dnl
     ⇒diversion one
     ⇒bar
     ⇒bar
     ⇒diversion three


Next:  ,Previous:  Undivert,Up:  Diversions

10.3 Diversion numbers

The current diversion is tracked by the builtindivnum:

— Builtin: divnum

Expands to the number of the current diversion.

     Initial divnum
     ⇒Initial 0
     divert(`1')
     Diversion one: divnum
     divert(`2')
     Diversion two: divnum
     ^D
     ⇒
     ⇒Diversion one: 1
     ⇒
     ⇒Diversion two: 2


Previous:  Divnum,Up:  Diversions

10.4 Discarding diverted text

Often it is not known, when output is diverted, whether the divertedtext is actually needed. Since all non-empty diversion are brought backon the main output stream when the end of input is seen, a method ofdiscarding a diversion is needed. If all diversions should bediscarded, the easiest is to end the input tom4 with‘divert(`-1')’ followed by an explicit ‘undivert’:

     divert(`1')
     Diversion one: divnum
     divert(`2')
     Diversion two: divnum
     divert(`-1')
     undivert
     ^D

No output is produced at all.

Clearing selected diversions can be done with the following macro:

— Composite: cleardivert ( [ diversions... ])

Discard the contents of each of the listed numeric diversions.

     define(`cleardivert',
     `pushdef(`_n', divnum)divert(`-1')undivert($@)divert(_n)popdef(`_n')')
     ⇒

It is called just like undivert, but the effect is to clear thediversions, given by the arguments. (This macro has a nasty bug! Youshould try to see if you can find it and correct it; or seeAnswers).


Next:  ,Previous:  Diversions,Up:  Top

11 Macros for text handling

There are a number of builtins in m4 for manipulating text invarious ways, extracting substrings, searching, substituting, and so on.


Next:  ,Up:  Text handling

11.1 Calculating length of strings

The length of a string can be calculated bylen:

— Builtin: len ( string)

Expands to the length of string, as a decimal number.

The macro len is recognized only with parameters.

     len()
     ⇒0
     len(`abcdef')
     ⇒6


Next:  ,Previous:  Len,Up:  Text handling

11.2 Searching for substrings

Searching for substrings is done withindex:

— Builtin: index ( string, substring)

Expands to the index of the first occurrence of substring instring. The first character instring has index 0. Ifsubstring does not occur in string,index expands to‘-1’.

The macro index is recognized only with parameters.

     index(`gnus, gnats, and armadillos', `nat')
     ⇒7
     index(`gnus, gnats, and armadillos', `dag')
     ⇒-1

Omitting substring evokes a warning, but still produces output;contrast this with an emptysubstring.

     index(`abc')
     error-->m4:stdin:1: Warning: too few arguments to builtin `index'
     ⇒0
     index(`abc', `')
     ⇒0
     index(`abc', `b')
     ⇒1


Next:  ,Previous:  Index macro,Up:  Text handling

11.3 Searching for regular expressions

Searching for regular expressions is done with the builtinregexp:

— Builtin: regexp ( string, regexp, [ replacement ])

Searches for regexp in string. The syntax for regularexpressions is the same as in GNU Emacs, which is similar toBRE, Basic Regular Expressions in POSIX. SeeSyntax of Regular Expressions in the GNU Emacs Manual. Support for ERE, Extended Regular Expressions is notavailable, but will be added in GNU M4 2.0.

If replacement is omitted, regexp expands to the index ofthe first match ofregexp in string. If regexp doesnot match anywhere instring, it expands to -1.

If replacement is supplied, and there was a match, regexpchanges the expansion to this argument, with ‘\n’ substitutedby the text matched by thenth parenthesized sub-expression ofregexp, up to nine sub-expressions. The escape ‘\&’ isreplaced by the text of the entire regular expression matched. Forall other characters, ‘\’ treats the next character literally. Awarning is issued if there were fewer sub-expressions than the‘\n’ requested, or if there is a trailing ‘\’. If therewas no match,regexp expands to the empty string.

The macro regexp is recognized only with parameters.

     regexp(`GNUs not Unix', `\<[a-z]\w+')
     ⇒5
     regexp(`GNUs not Unix', `\<Q\w*')
     ⇒-1
     regexp(`GNUs not Unix', `\w\(\w+\)$', `*** \& *** \1 ***')
     ⇒*** Unix *** nix ***
     regexp(`GNUs not Unix', `\<Q\w*', `*** \& *** \1 ***')
     ⇒

Here are some more examples on the handling of backslash:

     regexp(`abc', `\(b\)', `\\\10\a')
     ⇒\b0a
     regexp(`abc', `b', `\1\')
     error-->m4:stdin:2: Warning: sub-expression 1 not present
     error-->m4:stdin:2: Warning: trailing \ ignored in replacement
     ⇒
     regexp(`abc', `\(\(d\)?\)\(c\)', `\1\2\3\4\5\6')
     error-->m4:stdin:3: Warning: sub-expression 4 not present
     error-->m4:stdin:3: Warning: sub-expression 5 not present
     error-->m4:stdin:3: Warning: sub-expression 6 not present
     ⇒c

Omitting regexp evokes a warning, but still produces output;contrast this with an emptyregexp argument.

     regexp(`abc')
     error-->m4:stdin:1: Warning: too few arguments to builtin `regexp'
     ⇒0
     regexp(`abc', `')
     ⇒0
     regexp(`abc', `', `\\def')
     ⇒\def


Next:  ,Previous:  Regexp,Up:  Text handling

11.4 Extracting substrings

Substrings are extracted withsubstr:

— Builtin: substr ( string, from, [ length ])

Expands to the substring of string, which starts at indexfrom, and extends forlength characters, or to the end ofstring, if length is omitted. The starting index of a stringis always 0. The expansion is empty if there is an error parsingfrom orlength, if from is beyond the end ofstring, or iflength is negative.

The macro substr is recognized only with parameters.

     substr(`gnus, gnats, and armadillos', `6')
     ⇒gnats, and armadillos
     substr(`gnus, gnats, and armadillos', `6', `5')
     ⇒gnats

Omitting from evokes a warning, but still produces output.

     substr(`abc')
     error-->m4:stdin:1: Warning: too few arguments to builtin `substr'
     ⇒abc
     substr(`abc',)
     error-->m4:stdin:2: empty string treated as 0 in builtin `substr'
     ⇒abc


Next:  ,Previous:  Substr,Up:  Text handling

11.5 Translating characters

Character translation is done withtranslit:

— Builtin: translit ( string, chars, [ replacement ])

Expands to string, with each character that occurs inchars translated into the character fromreplacement withthe same index.

If replacement is shorter than chars, the excess charactersofchars are deleted from the expansion; if chars isshorter, the excess characters inreplacement are silentlyignored. If replacement is omitted, all characters instring that are present inchars are deleted from theexpansion. If a character appears more than once inchars, onlythe first instance is used in making the translation. Only a singletranslation pass is made, even if characters inreplacement alsoappear in chars.

As a GNU extension, both chars and replacement cancontain character-ranges, e.g., ‘a-z’ (meaning all lowercaseletters) or ‘0-9’ (meaning all digits). To include a dash ‘-’in chars or replacement, place it first or last in theentire string, or as the last character of a range. Back-to-back rangescan share a common endpoint. It is not an error for the last characterin the range to be `larger' than the first. In that case, the rangeruns backwards, i.e., ‘9-0’ means the string ‘9876543210’. The expansion of a range is dependent on the underlying encoding ofcharacters, so using ranges is not always portable between machines.

The macro translit is recognized only with parameters.

     translit(`GNUs not Unix', `A-Z')
     ⇒s not nix
     translit(`GNUs not Unix', `a-z', `A-Z')
     ⇒GNUS NOT UNIX
     translit(`GNUs not Unix', `A-Z', `z-a')
     ⇒tmfs not fnix
     translit(`+,-12345', `+--1-5', `<;>a-c-a')
     ⇒<;>abcba
     translit(`abcdef', `aabdef', `bcged')
     ⇒bgced

In the ascii encoding, the first example deletes all uppercaseletters, the second converts lowercase to uppercase, and the third`mirrors' all uppercase letters, while converting them to lowercase. The two first cases are by far the most common, even though they are notportable to ebcdic or other encodings. The fourth example shows arange ending in ‘-’, as well as back-to-back ranges. The finalexample shows that ‘a’ is mapped to ‘b’, not ‘c’; theresulting ‘b’ is not further remapped to ‘g’; the ‘d’ and‘e’ are swapped, and the ‘f’ is discarded.

Omitting chars evokes a warning, but still produces output.

     translit(`abc')
     error-->m4:stdin:1: Warning: too few arguments to builtin `translit'
     ⇒abc


Next:  ,Previous:  Translit,Up:  Text handling

11.6 Substituting text by regular expression

Global substitution in a string is done by patsubst:

— Builtin: patsubst ( string, regexp, [ replacement ])

Searches string for matches of regexp, and substitutesreplacement for each match. The syntax for regular expressionsis the same as in GNU Emacs (seeRegexp).

The parts of string that are not covered by any match ofregexp are copied to the expansion. Whenever a match is found, thesearch proceeds from the end of the match, so a character fromstring will never be substituted twice. If regexp matches astring of zero length, the start position for the search is incremented,to avoid infinite loops.

When a replacement is to be made, replacement is inserted intothe expansion, with ‘\n’ substituted by the text matched bythenth parenthesized sub-expression of patsubst, for up tonine sub-expressions. The escape ‘\&’ is replaced by the text ofthe entire regular expression matched. For all other characters,‘\’ treats the next character literally. A warning is issued ifthere were fewer sub-expressions than the ‘\n’ requested, orif there is a trailing ‘\’.

The replacement argument can be omitted, in which case the textmatched byregexp is deleted.

The macro patsubst is recognized only with parameters.

     patsubst(`GNUs not Unix', `^', `OBS: ')
     ⇒OBS: GNUs not Unix
     patsubst(`GNUs not Unix', `\<', `OBS: ')
     ⇒OBS: GNUs OBS: not OBS: Unix
     patsubst(`GNUs not Unix', `\w*', `(\&)')
     ⇒(GNUs)() (not)() (Unix)()
     patsubst(`GNUs not Unix', `\w+', `(\&)')
     ⇒(GNUs) (not) (Unix)
     patsubst(`GNUs not Unix', `[A-Z][a-z]+')
     ⇒GN not 
     patsubst(`GNUs not Unix', `not', `NOT\')
     error-->m4:stdin:6: Warning: trailing \ ignored in replacement
     ⇒GNUs NOT Unix

Here is a slightly more realistic example, which capitalizes individualwords or whole sentences, by substituting calls of the macrosupcase anddowncase into the strings.

— Composite: upcase ( text)
— Composite: downcase ( text)
— Composite: capitalize ( text)

Expand to text, but with capitalization changed: upcasechanges all letters to upper case,downcase changes all lettersto lower case, and capitalize changes the first character of eachword to upper case and the remaining characters to lower case.

First, an example of their usage, using implementations distributed inm4-1.4.16/examples/capitalize.m4.

     $ m4 -I examples
     include(`capitalize.m4')
     ⇒
     upcase(`GNUs not Unix')
     ⇒GNUS NOT UNIX
     downcase(`GNUs not Unix')
     ⇒gnus not unix
     capitalize(`GNUs not Unix')
     ⇒Gnus Not Unix

Now for the implementation. There is a helper macro _capitalizewhich puts only its first word in mixed case. Thencapitalizemerely parses out the words, and replaces them with an invocation of_capitalize. (As presented here, thecapitalize macro hassome subtle flaws. You should try to see if you can find and correctthem; or seeAnswers).

     $ m4 -I examples
     undivert(`capitalize.m4')dnl
     ⇒divert(`-1')
     ⇒# upcase(text)
     ⇒# downcase(text)
     ⇒# capitalize(text)
     ⇒#   change case of text, simple version
     ⇒define(`upcase', `translit(`$*', `a-z', `A-Z')')
     ⇒define(`downcase', `translit(`$*', `A-Z', `a-z')')
     ⇒define(`_capitalize',
     ⇒       `regexp(`$1', `^\(\w\)\(\w*\)',
     ⇒               `upcase(`\1')`'downcase(`\2')')')
     ⇒define(`capitalize', `patsubst(`$1', `\w+', `_$0(`\&')')')
     ⇒divert`'dnl

While regexp replaces the whole input with the replacement assoon as there is a match,patsubst replaces eachoccurrence of a match and preserves non-matching pieces:

     define(`patreg',
     `patsubst($@)
     regexp($@)')dnl
     patreg(`bar foo baz Foo', `foo\|Foo', `FOO')
     ⇒bar FOO baz FOO
     ⇒FOO
     patreg(`aba abb 121', `\(.\)\(.\)\1', `\2\1\2')
     ⇒bab abb 212
     ⇒bab

Omitting regexp evokes a warning, but still produces output;contrast this with an emptyregexp argument.

     patsubst(`abc')
     error-->m4:stdin:1: Warning: too few arguments to builtin `patsubst'
     ⇒abc
     patsubst(`abc', `')
     ⇒abc
     patsubst(`abc', `', `\\-')
     ⇒\-a\-b\-c\-


Previous:  Patsubst,Up:  Text handling

11.7 Formatting strings (printf-like)

Formatted output can be made withformat:

— Builtin: format ( format-string, ...)

Works much like the C function printf. The first argumentformat-string can contain ‘%’ specifications which aresatisfied by additional arguments, and the expansion offormat isthe formatted string.

The macro format is recognized only with parameters.

Its use is best described by a few examples:

     define(`foo', `The brown fox jumped over the lazy dog')
     ⇒
     format(`The string "%s" uses %d characters', foo, len(foo))
     ⇒The string "The brown fox jumped over the lazy dog" uses 38 characters
     format(`%*.*d', `-1', `-1', `1')
     ⇒1
     format(`%.0f', `56789.9876')
     ⇒56790
     len(format(`%-*X', `5000', `1'))
     ⇒5000
     ifelse(format(`%010F', `infinity'), `       INF', `success',
            format(`%010F', `infinity'), `  INFINITY', `success',
            format(`%010F', `infinity'))
     ⇒success
     ifelse(format(`%.1A', `1.999'), `0X1.0P+1', `success',
            format(`%.1A', `1.999'), `0X2.0P+0', `success',
            format(`%.1A', `1.999'))
     ⇒success
     format(`%g', `0xa.P+1')
     ⇒20

Using the forloop macro defined earlier (see Forloop), thisexample shows howformat can be used to produce tabular output.

     $ m4 -I examples
     include(`forloop.m4')
     ⇒
     forloop(`i', `1', `10', `format(`%6d squared is %10d
     ', i, eval(i**2))')
     ⇒     1 squared is          1
     ⇒     2 squared is          4
     ⇒     3 squared is          9
     ⇒     4 squared is         16
     ⇒     5 squared is         25
     ⇒     6 squared is         36
     ⇒     7 squared is         49
     ⇒     8 squared is         64
     ⇒     9 squared is         81
     ⇒    10 squared is        100
     ⇒

The builtin format is modeled after the ANSI C ‘printf’function, and supports these ‘%’ specifiers: ‘c’, ‘s’,‘d’, ‘o’, ‘x’, ‘X’, ‘u’, ‘a’, ‘A’,‘e’, ‘E’, ‘f’, ‘F’, ‘g’, ‘G’, and‘%’; it supports field widths and precisions, and the flags‘+’, ‘-’, ‘’, ‘0’, ‘#’, and ‘'’. Forinteger specifiers, the width modifiers ‘hh’, ‘h’, and‘l’ are recognized, and for floating point specifiers, the widthmodifier ‘l’ is recognized. Items not yet supported includepositional arguments, the ‘n’, ‘p’, ‘S’, and ‘C’specifiers, the ‘z’, ‘t’, ‘j’, ‘L’ and ‘ll’modifiers, and any platform extensions available in the nativeprintf. For more details on the functioning ofprintf,see the C Library Manual, or the POSIX specification (forexample, ‘%a’ is supported even on platforms that haven't yetimplemented C99 hexadecimal floating point output natively).

Unrecognized specifiers result in a warning. It is anticipated that afuture release of GNUm4 will support more specifiers,and give better warnings when various problems such as overflow areencountered. Likewise, escape sequences are not yet recognized.

     format(`%p', `0')
     error-->m4:stdin:1: Warning: unrecognized specifier in `%p'
     ⇒


Next:  ,Previous:  Text handling,Up:  Top

12 Macros for doing arithmetic

Integer arithmetic is included inm4, with a C-like syntax. Asconvenient shorthands, there are builtins for simple increment anddecrement operations.


Next:  ,Up:  Arithmetic

12.1 Decrement and increment operators

Increment and decrement of integers are supported using the builtinsincr anddecr:

— Builtin: incr ( number)
— Builtin: decr ( number)

Expand to the numerical value of number, incrementedor decremented, respectively, by one. Except for the empty string, theexpansion is empty ifnumber could not be parsed.

The macros incr and decr are recognized only withparameters.

     incr(`4')
     ⇒5
     decr(`7')
     ⇒6
     incr()
     error-->m4:stdin:3: empty string treated as 0 in builtin `incr'
     ⇒1
     decr()
     error-->m4:stdin:4: empty string treated as 0 in builtin `decr'
     ⇒-1


Previous:  Incr,Up:  Arithmetic

12.2 Evaluating integer expressions

Integer expressions are evaluated witheval:

— Builtin: eval ( expression, [ radix = ‘ 10 ] , [ width ])

Expands to the value of expression. The expansion is emptyif a problem is encountered while parsing the arguments. If specified,radix andwidth control the format of the output.

Calculations are done with 32-bit signed numbers. Overflow silentlyresults in wraparound. A warning is issued if division by zero isattempted, or ifexpression could not be parsed.

Expressions can contain the following operators, listed in order ofdecreasing precedence.

()
Parentheses
+ - ~ !
Unary plus and minus, and bitwise and logical negation
**
Exponentiation
* / %
Multiplication, division, and modulo
+ -
Addition and subtraction
<< >>
Shift left or right
> >= < <=
Relational operators
== !=
Equality operators
&
Bitwise and
^
Bitwise exclusive-or
|
Bitwise or
&&
Logical and
||
Logical or

The macro eval is recognized only with parameters.

All binary operators, except exponentiation, are left associative. Coperators that perform variable assignment, such as ‘+=’ or‘--’, are not implemented, sinceeval only operates onconstants, not variables. Attempting to use them results in an error. However, since traditional implementations treated ‘=’ as anundocumented alias for ‘==’ as opposed to an assignment operator,this usage is supported as a special case. Be aware that a futureversion of GNU M4 may support assignment semantics as anextension when POSIX mode is not requested, and that using‘=’ to check equality is not portable.

     eval(`2 = 2')
     error-->m4:stdin:1: Warning: recommend ==, not =, for equality operator
     ⇒1
     eval(`++0')
     error-->m4:stdin:2: invalid operator in eval: ++0
     ⇒
     eval(`0 |= 1')
     error-->m4:stdin:3: invalid operator in eval: 0 |= 1
     ⇒

Note that some older m4 implementations use ‘^’ as analternate operator for the exponentiation, although POSIXrequires the C behavior of bitwise exclusive-or. The precedence of thenegation operators, ‘~’ and ‘!’, was traditionally lower thanequality. The unary operators could not be used reliably more than onceon the same term without intervening parentheses. The traditionalprecedence of the equality operators ‘==’ and ‘!=’ wasidentical instead of lower than the relational operators such as‘<’, even through GNU M4 1.4.8. Starting with version1.4.9, GNU M4 correctly follows POSIX precedencerules. M4 scripts designed to be portable between releases must beaware that parentheses may be required to enforce C precedence rules. Likewise, division by zero, even in the unused branch of ashort-circuiting operator, is not always well-defined in otherimplementations.

Following are some examples where the current version of M4 follows Cprecedence rules, but where older versions and some otherimplementations ofm4 require explicit parentheses to get thecorrect result:

     eval(`1 == 2 > 0')
     ⇒1
     eval(`(1 == 2) > 0')
     ⇒0
     eval(`! 0 * 2')
     ⇒2
     eval(`! (0 * 2)')
     ⇒1
     eval(`1 | 1 ^ 1')
     ⇒1
     eval(`(1 | 1) ^ 1')
     ⇒0
     eval(`+ + - ~ ! ~ 0')
     ⇒1
     eval(`2 || 1 / 0')
     ⇒1
     eval(`0 || 1 / 0')
     error-->m4:stdin:9: divide by zero in eval: 0 || 1 / 0
     ⇒
     eval(`0 && 1 % 0')
     ⇒0
     eval(`2 && 1 % 0')
     error-->m4:stdin:11: modulo by zero in eval: 2 && 1 % 0
     ⇒

As a GNU extension, the operator ‘**’ performs integralexponentiation. The operator is right-associative, and if evaluated,the exponent must be non-negative, and at least one of the argumentsmust be non-zero, or a warning is issued.

     eval(`2 ** 3 ** 2')
     ⇒512
     eval(`(2 ** 3) ** 2')
     ⇒64
     eval(`0 ** 1')
     ⇒0
     eval(`2 ** 0')
     ⇒1
     eval(`0 ** 0')
     ⇒
     error-->m4:stdin:5: divide by zero in eval: 0 ** 0
     eval(`4 ** -2')
     error-->m4:stdin:6: negative exponent in eval: 4 ** -2
     ⇒

Within expression, (but not radix or width), numberswithout a special prefix are decimal. A simple ‘0’ prefixintroduces an octal number. ‘0x’ introduces a hexadecimal number. As GNU extensions, ‘0b’ introduces a binary number. ‘0r’ introduces a number expressed in any radix between 1 and 36:the prefix should be immediately followed by the decimal expression ofthe radix, a colon, then the digits making the number. For radix 1,leading zeros are ignored, and all remaining digits must be ‘1’;for all other radices, the digits are ‘0’, ‘1’, ‘2’,.... Beyond ‘9’, the digits are ‘a’, ‘b... upto ‘z’. Lower and upper case letters can be used interchangeablyin numbers prefixes and as number digits.

Parentheses may be used to group subexpressions whenever needed. For therelational operators, a true relation returns1, and a falserelation return 0.

Here are a few examples of use of eval.

     eval(`-3 * 5')
     ⇒-15
     eval(`-99 / 10')
     ⇒-9
     eval(`-99 % 10')
     ⇒-9
     eval(`99 % -10')
     ⇒9
     eval(index(`Hello world', `llo') >= 0)
     ⇒1
     eval(`0r1:0111 + 0b100 + 0r3:12')
     ⇒12
     define(`square', `eval(`($1) ** 2')')
     ⇒
     square(`9')
     ⇒81
     square(square(`5')` + 1')
     ⇒676
     define(`foo', `666')
     ⇒
     eval(`foo / 6')
     error-->m4:stdin:11: bad expression in eval: foo / 6
     ⇒
     eval(foo / 6)
     ⇒111

As the last two lines show, eval does not handle macronames, even if they expand to a valid expression (or part of a validexpression). Therefore all macros must be expanded before they arepassed toeval.

Some calculations are not portable to other implementations, since theyhave undefined semantics in C, but GNUm4 haswell-defined behavior on overflow. When shifting, an out-of-range shiftamount is implicitly brought into the range of 32-bit signed integersusing an implicit bit-wise and with 0x1f).

     define(`max_int', eval(`0x7fffffff'))
     ⇒
     define(`min_int', incr(max_int))
     ⇒
     eval(min_int` < 0')
     ⇒1
     eval(max_int` > 0')
     ⇒1
     ifelse(eval(min_int` / -1'), min_int, `overflow occurred')
     ⇒overflow occurred
     min_int
     ⇒-2147483648
     eval(`0x80000000 % -1')
     ⇒0
     eval(`-4 >> 1')
     ⇒-2
     eval(`-4 >> 33')
     ⇒-2

If radix is specified, it specifies the radix to be used in theexpansion. The default radix is 10; this is also the case ifradix is the empty string. A warning results if the radix isoutside the range of 1 through 36, inclusive. The result of evalis always taken to be signed. No radix prefix is output, and forradices greater than 10, the digits are lower case. Thewidthargument specifies the minimum output width, excluding any negativesign. The result is zero-padded to extend the expansion to therequested width. A warning results if the width is negative. Ifradix orwidth is out of bounds, the expansion ofeval is empty.

     eval(`666', `10')
     ⇒666
     eval(`666', `11')
     ⇒556
     eval(`666', `6')
     ⇒3030
     eval(`666', `6', `10')
     ⇒0000003030
     eval(`-666', `6', `10')
     ⇒-0000003030
     eval(`10', `', `0')
     ⇒10
     `0r1:'eval(`10', `1', `11')
     ⇒0r1:01111111111
     eval(`10', `16')
     ⇒a
     eval(`1', `37')
     error-->m4:stdin:9: radix 37 in builtin `eval' out of range
     ⇒
     eval(`1', , `-1')
     error-->m4:stdin:10: negative width to builtin `eval'
     ⇒
     eval()
     error-->m4:stdin:11: empty string treated as 0 in builtin `eval'
     ⇒0


Next:  ,Previous:  Arithmetic,Up:  Top

13 Macros for running shell commands

There are a few builtin macros in m4 that allow you to run shellcommands from withinm4.

Note that the definition of a valid shell command is system dependent. On UNIX systems, this is the typical/bin/sh. But on othersystems, such as native Windows, the shell has a different syntax ofcommands that it understands. Some examples in this chapter assume/bin/sh, and also demonstrate how to quit early with a knownexit value if this is not the case.


Next:  ,Up:  Shell commands

13.1 Determining the platform

Sometimes it is desirable for an input file to know which platformm4 is running on. GNUm4 provides severalmacros that are predefined to expand to the empty string; checking fortheir existence will confirm platform details.

— Optional builtin: __gnu__
— Optional builtin: __os2__
— Optional builtin: os2
— Optional builtin: __unix__
— Optional builtin: unix
— Optional builtin: __windows__
— Optional builtin: windows

Each of these macros is conditionally defined as needed to describe theenvironment ofm4. If defined, each macro expands to the emptystring. For now, these macros silently ignore all arguments, but in afuture release of M4, they might warn if arguments are present.

When GNU extensions are in effect (that is, when you did notuse the -G option, seeInvoking m4),GNU m4 will define the macro__gnu__ toexpand to the empty string.

     $ m4
     __gnu__
     ⇒
     __gnu__(`ignored')
     ⇒
     Extensions are ifdef(`__gnu__', `active', `inactive')
     ⇒Extensions are active
     $ m4 -G
     __gnu__
     ⇒__gnu__
     __gnu__(`ignored')
     ⇒__gnu__(ignored)
     Extensions are ifdef(`__gnu__', `active', `inactive')
     ⇒Extensions are inactive

On UNIX systems, GNU m4 will define __unix__by default, orunix when the -G option is specified.

On native Windows systems, GNU m4 will define__windows__ by default, orwindows when the-G option is specified.

On OS/2 systems, GNU m4 will define __os2__by default, oros2 when the -G option is specified.

If GNU m4 does not provide a platform macro for your system,please report that as a bug.

     define(`provided', `0')
     ⇒
     ifdef(`__unix__', `define(`provided', incr(provided))')
     ⇒
     ifdef(`__windows__', `define(`provided', incr(provided))')
     ⇒
     ifdef(`__os2__', `define(`provided', incr(provided))')
     ⇒
     provided
     ⇒1


Next:  ,Previous:  Platform macros,Up:  Shell commands

13.2 Executing simple commands

Any shell command can be executed, using syscmd:

— Builtin: syscmd ( shell-command)

Executes shell-command as a shell command.

The expansion of syscmd is void, not the output fromshell-command! Output or error messages fromshell-commandare not read by m4. See Esyscmd, if you need to process thecommand output.

Prior to executing the command, m4 flushes its buffers. The default standard input, output and error ofshell-command arethe same as those of m4.

By default, the shell-command will be used as the argument to the-c option of the/bin/sh shell (or the version ofsh specified by ‘command -p getconf PATH’, if your systemsupports that). If you prefer a different shell, theconfigure script can be given the option--with-syscmd-shell=location to set the location of analternative shell at GNUm4 installation; thealternative shell must still support -c.

The macro syscmd is recognized only with parameters.

     define(`foo', `FOO')
     ⇒
     syscmd(`echo foo')
     ⇒foo
     ⇒

Note how the expansion of syscmd keeps the trailing newline ofthe command, as well as using the newline that appeared after the macro.

The following is an example of shell-command using the samestandard input asm4:

     $ echo "m4wrap(\`syscmd(\`cat')')" | m4

It tells m4 to read all of its input before executing the wrappedtext, then hand a valid (albeit emptied) pipe as standard input for thecat subcommand. Therefore, you should be careful when usingstandard input (either by specifying no files, or by passing ‘-’ asa file name on the command line, seeInvoking m4), and also invoking subcommands viasyscmd or esyscmdthat consume data from standard input. When standard input is aseekable file, the subprocess will pick up with the next character notyet processed bym4; when it is a pipe or other non-seekablefile, there is no guarantee how much data will already be buffered bym4 and thus unavailable to the child.


Next:  ,Previous:  Syscmd,Up:  Shell commands

13.3 Reading the output of commands

If you want m4 to read the output of a shell command, useesyscmd:

— Builtin: esyscmd ( shell-command)

Expands to the standard output of the shell commandshell-command.

Prior to executing the command, m4 flushes its buffers. The default standard input and standard error ofshell-command arethe same as those of m4. The error output ofshell-commandis not a part of the expansion: it will appear along with the erroroutput ofm4.

By default, the shell-command will be used as the argument to the-c option of the/bin/sh shell (or the version ofsh specified by ‘command -p getconf PATH’, if your systemsupports that). If you prefer a different shell, theconfigure script can be given the option--with-syscmd-shell=location to set the location of analternative shell at GNUm4 installation; thealternative shell must still support -c.

The macro esyscmd is recognized only with parameters.

     define(`foo', `FOO')
     ⇒
     esyscmd(`echo foo')
     ⇒FOO
     ⇒

Note how the expansion of esyscmd keeps the trailing newline ofthe command, as well as using the newline that appeared after the macro.

Just as with syscmd, care must be exercised when sharing standardinput betweenm4 and the child process of esyscmd.


Next:  ,Previous:  Esyscmd,Up:  Shell commands

13.4 Exit status

To see whether a shell command succeeded, use sysval:

— Builtin: sysval

Expands to the exit status of the last shell command run withsyscmd oresyscmd. Expands to 0 if no command has beenrun yet.

     sysval
     ⇒0
     syscmd(`false')
     ⇒
     ifelse(sysval, `0', `zero', `non-zero')
     ⇒non-zero
     syscmd(`exit 2')
     ⇒
     sysval
     ⇒2
     syscmd(`true')
     ⇒
     sysval
     ⇒0
     esyscmd(`false')
     ⇒
     ifelse(sysval, `0', `zero', `non-zero')
     ⇒non-zero
     esyscmd(`echo dnl && exit 127')
     ⇒
     sysval
     ⇒127
     esyscmd(`true')
     ⇒
     sysval
     ⇒0

sysval results in 127 if there was a problem executing thecommand, for example, if the system-imposed argument length is exceeded,or if there were not enough resources to fork. It is not possible todistinguish between failed execution and successful execution that hadan exit status of 127, unless there was output from the child process.

On UNIX platforms, where it is possible to detect when command executionis terminated by a signal, rather than a normal exit, the result is thesignal number shifted left by eight bits.

     dnl This test assumes kill is a shell builtin, and that signals are
     dnl recognizable.
     ifdef(`__unix__', ,
           `errprint(` skipping: syscmd does not have unix semantics
     ')m4exit(`77')')dnl
     syscmd(`kill -9 $$')
     ⇒
     sysval
     ⇒2304
     syscmd()
     ⇒
     sysval
     ⇒0
     esyscmd(`kill -9 $$')
     ⇒
     sysval
     ⇒2304


Previous:  Sysval,Up:  Shell commands

13.5 Making temporary files

Commands specified tosyscmd or esyscmd might need atemporary file, for output or for some other purpose. There is abuiltin macro,mkstemp, for making a temporary file:

— Builtin: mkstemp ( template)
— Builtin: maketemp ( template)

Expands to the quoted name of a new, empty file, made from the stringtemplate, which should end with the string ‘XXXXXX’. The six‘X’ characters are then replaced with random characters matchingthe regular expression ‘[a-zA-Z0-9._-]’, in order to make the filename unique. If fewer than six ‘X’ characters are found at the endoftemplate, the result will be longer than the template. Thecreated file will have access permissions as if bychmod =rw,go=,meaning that the current umask of the m4 process is taken intoaccount, and at most only the current user can read and write the file.

The traditional behavior, standardized by POSIX, is thatmaketemp merely replaces the trailing ‘X’ with the processid, without creating a file or quoting the expansion, and withoutensuring that the resultingstring is a unique file name. In part, this means that using the sametemplate twice in the same input file will result in the sameexpansion. This behavior is a security hole, as it is very easy foranother process to guess the name that will be generated, and thusinterfere with a subsequent use of syscmd trying to manipulatethat file name. Hence, POSIX has recommended that all newimplementations ofm4 provide the secure mkstemp builtin,and that users ofm4 check for its existence.

The expansion is void and an error issued if a temporary file couldnot be created.

The macros mkstemp and maketemp are recognized only withparameters.

If you try this next example, you will most likely get different outputfor the two file names, since the replacement characters are randomlychosen:

     $ m4
     define(`tmp', `oops')
     ⇒
     maketemp(`/tmp/fooXXXXXX')
     ⇒/tmp/fooa07346
     ifdef(`mkstemp', `define(`maketemp', defn(`mkstemp'))',
           `define(`mkstemp', defn(`maketemp'))dnl
     errprint(`warning: potentially insecure maketemp implementation
     ')')
     ⇒
     mkstemp(`doc')
     ⇒docQv83Uw

Unless you use the --traditional command line option (or-G, seeInvoking m4), the GNUversion of maketemp is secure. This means that using the sametemplate to multiple calls will generate multiple files. However, werecommend that you use the newmkstemp macro, introduced inGNU M4 1.4.8, which is secure even in traditional mode. Also,as of M4 1.4.11, the secure implementation quotes the resulting filename, so that you are guaranteed to know what file was created even ifthe random file name happens to match an existing macro. Notice thatthis example is careful to use defn to avoid unintended expansionof ‘foo’.

     $ m4
     define(`foo', `errprint(`oops')')
     ⇒
     syscmd(`rm -f foo-??????')sysval
     ⇒0
     define(`file1', maketemp(`foo-XXXXXX'))dnl
     ifelse(esyscmd(`echo \` foo-?????? \''), ` foo-?????? ',
            `no file', `created')
     ⇒created
     define(`file2', maketemp(`foo-XX'))dnl
     define(`file3', mkstemp(`foo-XXXXXX'))dnl
     ifelse(len(defn(`file1')), len(defn(`file2')),
            `same length', `different')
     ⇒same length
     ifelse(defn(`file1'), defn(`file2'), `same', `different file')
     ⇒different file
     ifelse(defn(`file2'), defn(`file3'), `same', `different file')
     ⇒different file
     ifelse(defn(`file1'), defn(`file3'), `same', `different file')
     ⇒different file
     syscmd(`rm 'defn(`file1') defn(`file2') defn(`file3'))
     ⇒
     sysval
     ⇒0


Next:  ,Previous:  Shell commands,Up:  Top

14 Miscellaneous builtin macros

This chapter describes various builtins, that do not really belong inany of the previous chapters.


Next:  ,Up:  Miscellaneous

14.1 Printing error messages

You can print error messages usingerrprint:

— Builtin: errprint ( message, ...)

Prints message and the rest of the arguments to standard error,separated by spaces. Standard error is used, regardless of the--debugfile option (seeInvoking m4).

The expansion of errprint is void. The macro errprint is recognized only with parameters.

     errprint(`Invalid arguments to forloop
     ')
     error-->Invalid arguments to forloop
     ⇒
     errprint(`1')errprint(`2',`3
     ')
     error-->12 3
     ⇒

A trailing newline is not printed automatically, so it should besupplied as part of the argument, as in the example. Unfortunately, theexact output oferrprint is not very portable to other m4implementations: POSIX requires that all arguments be printed,but some implementations ofm4 only print the first. Furthermore, some BSD implementations always append a newlinefor eacherrprint call, regardless of whether the last argumentalready had one, and POSIX is silent on whether this isacceptable.


Next:  ,Previous:  Errprint,Up:  Miscellaneous

14.2 Printing current location

To make it possible to specify the location of an error, threeutility builtins exist:

— Builtin: __file__
— Builtin: __line__
— Builtin: __program__

Expand to the quoted name of the current input file, thecurrent input line number in that file, and the quoted name of thecurrent invocation ofm4.

     errprint(__program__:__file__:__line__: `input error
     ')
     error-->m4:stdin:1: input error
     ⇒

Line numbers start at 1 for each file. If the file was found due to the-I option orM4PATH environment variable, that isreflected in the file name. The syncline option (-s,seeInvoking m4), and the‘f’ and ‘l’ flags ofdebugmode (see Debug Levels),also use this notion of current file and line. Redefining the threelocation macros has no effect on syncline, debug, warning, or errormessage output.

This example reuses the file incl.m4 mentioned earlier(seeInclude):

     $ m4 -I examples
     define(`foo', ``$0' called at __file__:__line__')
     ⇒
     foo
     ⇒foo called at stdin:2
     include(`incl.m4')
     ⇒Include file start
     ⇒foo called at examples/incl.m4:2
     ⇒Include file end
     ⇒

The location of macros invoked during the rescanning of macro expansiontext corresponds to the location in the file where the expansion wastriggered, regardless of how many newline characters the expansion textcontains. As of GNU M4 1.4.8, the location of text wrappedwith m4wrap (see M4wrap) is the point at which them4wrap was invoked. Previous versions, however, behaved asthough wrapped text came from line 0 of the file “”.

     define(`echo', `$@')
     ⇒
     define(`foo', `echo(__line__
     __line__)')
     ⇒
     echo(__line__
     __line__)
     ⇒4
     ⇒5
     m4wrap(`foo
     ')
     ⇒
     foo(errprint(__line__
     __line__
     ))
     error-->8
     error-->9
     ⇒8
     ⇒8
     __line__
     ⇒11
     m4wrap(`__line__
     ')
     ⇒
     ^D
     ⇒12
     ⇒6
     ⇒6

The __program__ macro behaves like ‘$0’ in shellterminology. If you invokem4 through an absolute path or a linkwith a different spelling, rather than by relying on aPATH searchfor plain ‘m4’, it will affect how__program__ expands. The intent is that you can use it to produce error messages with thesame formatting thatm4 produces internally. It can also be usedwithin syscmd (seeSyscmd) to pick the same version ofm4 that is currently running, rather than whatever version ofm4 happens to be first inPATH. It was first introduced inGNU M4 1.4.6.


Previous:  Location,Up:  Miscellaneous

14.3 Exiting from m4

If you need to exit fromm4 before the entire input has beenread, you can use m4exit:

— Builtin: m4exit ( [ code = ‘ 0 ])

Causes m4 to exit, with exit status code. If code isleft out, the exit status is zero. Ifcode cannot be parsed, oris outside the range of 0 to 255, the exit status is one. No furtherinput is read, and all wrapped and diverted text is discarded.

     m4wrap(`This text is lost due to `m4exit'.')
     ⇒
     divert(`1') So is this.
     divert
     ⇒
     m4exit And this is never read.

A common use of this is to abort processing:

— Composite: fatal_error ( message)

Abort processing with an error message and non-zero status. Prefixmessage with details about where the error occurred, and print theresulting string to standard error.

     define(`fatal_error',
            `errprint(__program__:__file__:__line__`: fatal error: $*
     ')m4exit(`1')')
     ⇒
     fatal_error(`this is a BAD one, buster')
     error-->m4:stdin:4: fatal error: this is a BAD one, buster

After this macro call, m4 will exit with exit status 1. This macrois only intended for error exits, since the normal exit procedures arenot followed, i.e., diverted text is not undiverted, and saved text(seeM4wrap) is not reread. (This macro could be made more robustto earlier versions ofm4. You should try to see if you can findweaknesses and correct them; or seeAnswers).

Note that it is still possible for the exit status to be different thanwhat was requested bym4exit. If m4 detects some othererror, such as a write error on standard output, the exit status will benon-zero even ifm4exit requested zero.

If standard input is seekable, then the file will be positioned at thenext unread character. If it is a pipe or other non-seekable file,then there are no guarantees how much datam4 might have readinto buffers, and thus discarded.


Next:  ,Previous:  Miscellaneous,Up:  Top

15 Fast loading of frozen state

Some bigger m4 applications may be built over a common basecontaining hundreds of definitions and other costly initializations. Usually, the common base is kept in one or more declarative files,which files are listed on eachm4 invocation prior to theuser's input file, or else each input file usesinclude.

Reading the common base of a big application, over and over again, maybe time consuming. GNUm4 offers some machinery tospeed up the start of an application using lengthy common bases.

15.1 Using frozen files

Suppose a user has a library of m4 initializations inbase.m4, which is then used with multiple input files:

     $ m4 base.m4 input1.m4
     $ m4 base.m4 input2.m4
     $ m4 base.m4 input3.m4

Rather than spending time parsing the fixed contents of base.m4every time, the user might rather execute:

     $ m4 -F base.m4f base.m4

once, and further execute, as often as needed:

     $ m4 -R base.m4f input1.m4
     $ m4 -R base.m4f input2.m4
     $ m4 -R base.m4f input3.m4

with the varying input. The first call, containing the -Foption, only reads and executes file base.m4, definingvarious application macros and computing other initializations. Once the input filebase.m4 has been completely processed, GNUm4 produces inbase.m4f a frozen file, that is, afile which contains a kind of snapshot of them4 internal state.

Later calls, containing the -R option, are able to reloadthe internal state ofm4, from base.m4f,prior to reading any other input files. This meansinstead of starting with a virgin copy ofm4, input will beread after having effectively recovered the effect of a prior run. In our example, the effect is the same as if filebase.m4 hasbeen read anew. However, this effect is achieved a lot faster.

Only one frozen file may be created or read in any one m4invocation. It is not possible to recover two frozen files at once. However, frozen files may be updated incrementally, through using-R and-F options simultaneously. For example, ifsome care is taken, the command:

     $ m4 file1.m4 file2.m4 file3.m4 file4.m4

could be broken down in the following sequence, accumulating the sameoutput:

     $ m4 -F file1.m4f file1.m4
     $ m4 -R file1.m4f -F file2.m4f file2.m4
     $ m4 -R file2.m4f -F file3.m4f file3.m4
     $ m4 -R file3.m4f file4.m4

Some care is necessary because not every effort has been made forthis to work in all cases. In particular, the trace attribute ofmacros is not handled, nor the current setting ofchangeword. Currently, m4wrap and sysval also have problems. Also, interactions for some options ofm4, being used in one calland not in the next, have not been fully analyzed yet. On the otherend, you may be confident that stacks ofpushdef definitionsare handled correctly, as well as undefined or renamed builtins, andchanged strings for quotes or comments. And future releases ofGNU M4 will improve on the utility of frozen files.

When an m4 run is to be frozen, the automatic undiversionwhich takes place at end of execution is inhibited. Instead, allpositively numbered diversions are saved into the frozen file. The active diversion number is also transmitted.

A frozen file to be reloaded need not reside in the current directory. It is looked up the same way as aninclude file (see Search Path).

If the frozen file was generated with a newer version of m4, andcontains directives that an olderm4 cannot parse, attempting toload the frozen file with option -R will cause m4 toexit with status 63 to indicate version mismatch.


Previous:  Using frozen files,Up:  Frozen files

15.2 Frozen file format

Frozen files are sharable across architectures. It is safe to writea frozen file on one machine and read it on another, given that thesecond machine uses the same or newer version of GNU m4. It is conventional, but not required, to give a frozen file the suffixof.m4f.

These are simple (editable) text files, made up of directives,each starting with a capital letter and ending with a newline(<NL>). Wherever a directive is expected, the character‘#’ introduces a comment line; empty lines are also ignored if theyare not part of an embedded string. In the following descriptions, eachlen refers to the length ofthe corresponding strings str in the next line of input. Numbersare always expressed in decimal. There are no escape characters. Thedirectives are:

C len1 , len2 <NL> str1 str2 <NL>
Uses str1 and str2 as the begin-comment andend-comment strings. If omitted, then ‘ #’ and <NL> are thecomment delimiters.
D number , len <NL> str <NL>
Selects diversion number, making it current, then copy str in the current diversion. number may be a negativenumber for a non-existing diversion. To merely specify an activeselection, use this command with an empty str. With 0 as thediversion number, str will be issued on standard outputat reload time. GNU m4 will not produce the ‘ D’directive with non-zero length for diversion 0, but this can be donewith manual edits. This directive mayappear more than once for the same diversion, in which case thediversion is the concatenation of the various uses. If omitted, thendiversion 0 is current.
F len1 , len2 <NL> str1 str2 <NL>
Defines, through pushdef, a definition for str1expanding to the function whose builtin name is str2. If thebuiltin does not exist (for example, if the frozen file was produced bya copy of m4 compiled with changeword support, but the versionof m4 reloading was compiled without it), the reload is silent,but any subsequent use of the definition of str1 will result ina warning. This directive may appear more than once for the same name,and its order, along with ‘ T’, is important. If omitted, you willhave no access to any builtins.
Q len1 , len2 <NL> str1 str2 <NL>
Uses str1 and str2 as the begin-quote and end-quotestrings. If omitted, then ‘ `’ and ‘ '’ are the quotedelimiters.
T len1 , len2 <NL> str1 str2 <NL>
Defines, though pushdef, a definition for str1expanding to the text given by str2. This directive may appearmore than once for the same name, and its order, along with ‘ F’, isimportant.
V number <NL>
Confirms the format of the file. m4 1.4.16 only createsand understands frozen files where number is 1. This directivemust be the first non-comment in the file, and may not appear more thanonce.


Next:  ,Previous:  Frozen files,Up:  Top

16 Compatibility with other versions of m4

This chapter describes the many of the differences between thisimplementation ofm4, and of other implementations found underUNIX, such as System V Release 3, Solaris, and BSD flavors. In particular, it lists the known differences and extensions toPOSIX. However, the list is not necessarily comprehensive.

At the time of this writing, POSIX 2001 (also known as IEEEStd 1003.1-2001) is the latest standard, although a new version ofPOSIX is under development and includes several proposals formodifying whatm4 is required to do. The requirements form4 are shared between SUSv3 and POSIX, andcan be viewed athttp://www.opengroup.org/onlinepubs/000095399/utilities/m4.html.

16.1 Extensions in GNU M4

This version ofm4 contains a few facilities that do not existin System V m4. These extra facilities are all suppressed byusing the-G command line option (see Invoking m4), unless overridden by other command line options.

  • In the $n notation for macro arguments, n can containseveral digits, while the System Vm4 only accepts one digit. This allows macros in GNU m4 to take any number ofarguments, and not only nine (seeArguments).

    This means that define(`foo', `$11') is ambiguous betweenimplementations. To portably choose between grabbing the firstparameter and appending 1 to the expansion, or grabbing the eleventhparameter, you can do the following:

              define(`a1', `A1')
              ⇒
              dnl First argument, concatenated with 1
              define(`_1', `$1')define(`first1', `_1($@)1')
              ⇒
              dnl Eleventh argument, portable
              define(`_9', `$9')define(`eleventh', `_9(shift(shift($@)))')
              ⇒
              dnl Eleventh argument, GNU style
              define(`Eleventh', `$11')
              ⇒
              first1(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k')
              ⇒A1
              eleventh(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k')
              ⇒k
              Eleventh(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k')
              ⇒k
    

    Also see the argn macro (see Shift).

  • The divert (see Divert) macro can manage more than 9diversions. GNUm4 treats all positive numbers as validdiversions, rather than discarding diversions greater than 9.
  • Files included with include and sinclude are sought in auser specified search path, if they are not found in the workingdirectory. The search path is specified by the-I option and theM4PATH environment variable (seeSearch Path).
  • Arguments to undivert can be non-numeric, in which case the namedfile will be included uninterpreted in the output (seeUndivert).
  • Formatted output is supported through the format builtin, whichis modeled after the C library functionprintf (see Format).
  • Searches and text substitution through basic regular expressions aresupported by theregexp (see Regexp) and patsubst(seePatsubst) builtins. Some BSD implementations useextended regular expressions instead.
  • The output of shell commands can be read into m4 withesyscmd (seeEsyscmd).
  • There is indirect access to any builtin macro with builtin(see Builtin).
  • Macros can be called indirectly through indir (see Indir).
  • The name of the program, the current input file, and the current inputline number are accessible through the builtins__program__,__file__, and __line__ (see Location).
  • The format of the output from dumpdef and macro tracing can becontrolled withdebugmode (see Debug Levels).
  • The destination of trace and debug output can be controlled withdebugfile (seeDebug Output).
  • The maketemp (see Mkstemp) macro behaves likemkstemp,creating a new file with a unique name on every invocation, rather thanfollowing the insecure behavior of replacing the trailing ‘X’characters with them4 process id.
  • POSIX only requires support for the command line options-s,-D, and -U, so all other options acceptedby GNU M4 are extensions. SeeInvoking m4, for adescription of these options.

    The debugging and tracing facilities in GNU m4 are muchmore extensive than in most other versions ofm4.

16.2 Facilities in System V m4 not in GNU m4

The version of m4 from System V contains a few facilities thathave not been implemented in GNUm4 yet. Additionally,POSIX requires some behaviors that GNU m4 has notimplemented yet. Relying on these behaviors is non-portable, as afuture release of GNUm4 may change.

  • POSIX requires support for multiple arguments to defn,without any clarification on howdefn behaves when one of themultiple arguments names a builtin. System Vm4 and some otherimplementations allow mixing builtins and text macros into a singlemacro. GNUm4 only supports joining multiple textarguments, although a future implementation may lift this restriction tobehave more like System V. The only portable way to join text macroswith builtins is via helper macros and implicit concatenation of macroresults.
  • POSIX requires an application to exit with non-zero status ifit wrote an error message to stderr. This has not yet been consistentlyimplemented for the various builtins that are required to issue an error(such aseval (see Eval) when an argument cannot be parsed).
  • Some traditional implementations only allow reading standard inputonce, but GNUm4 correctly handles multiple instancesof ‘-’ on the command line.
  • POSIX requires m4wrap (see M4wrap) to act in FIFO(first-in, first-out) order, but GNUm4 currently usesLIFO order. Furthermore, POSIX states that only the firstargument tom4wrap is saved for later evaluation, butGNU m4 saves and processes all arguments, with outputseparated by spaces.
  • POSIX states that builtins that require arguments, but arecalled without arguments, have undefined behavior. Traditionalimplementations simply behave as though empty strings had been passed. For example,a`'define`'b would expand to ab. ButGNU m4 ignores certain builtins if they have missingarguments, givingadefineb for the above example.
  • Traditional implementations handle define(`f',`1') (see Define)by undefining the entire stack of previous definitions, and if doingundefine(`f') first. GNUm4 replaces just the topdefinition on the stack, as if doing popdef(`f') followed bypushdef(`f',`1'). POSIX allows either behavior.
  • POSIX 2001 requires syscmd (see Syscmd) to evaluatecommand output for macro expansion, but this was a mistake that isanticipated to be corrected in the next version of POSIX. GNUm4 follows traditional behavior in syscmdwhere output is not rescanned, and provides the extensionesyscmdthat does scan the output.
  • At one point, POSIX required changequote(arg)(seeChangequote) to use newline as the close quote, but this was abug, and the next version of POSIX is anticipated to statethat using empty strings or just one argument is unspecified. Meanwhile, the GNUm4 behavior of treating an emptyend-quote delimiter as ‘'’ is not portable, as Solaris treats it asrepeating the start-quote delimiter, and BSD treats it as leaving theprevious end-quote delimiter unchanged. For predictable results, nevercall changequote with just one argument, or with empty strings forarguments.
  • At one point, POSIX required changecom(arg,)(seeChangecom) to make it impossible to end a comment, but this isa bug, and the next version of POSIX is anticipated to statethat using empty strings is unspecified. Meanwhile, the GNUm4 behavior of treating an empty end-comment delimiter as newlineis not portable, as BSD treats it as leaving the previous end-commentdelimiter unchanged. It is also impossible in BSD implementations todisable comments, even though that is required by POSIX. Forpredictable results, never call changecom with empty strings forarguments.
  • Most implementations of m4 give macros a higher precedence thancomments when parsing, meaning that if the start delimiter given tochangecom (seeChangecom) starts with a macro name, commentsare effectively disabled. POSIX does not specify what theprecedence is, so this version of GNUm4 parserrecognizes comments, then macros, then quoted strings.
  • Traditional implementations allow argument collection, but not stringand comment processing, to span file boundaries. Thus, ifa.m4contains ‘len(’, andb.m4 contains ‘abc)’,m4 a.m4 b.m4 outputs ‘3’ with traditionalm4, butgives an error message that the end of file was encountered inside amacro with GNUm4. On the other hand, traditionalimplementations do end of file processing for files included withinclude orsinclude (see Include), while GNUm4 seamlessly integrates the content of those files. Thusinclude(`a.m4')include(`b.m4') will output ‘3’ instead ofgiving an error.
  • Traditional m4 treats traceon (see Trace) withoutarguments as a global variable, independent of named macro tracing. Also, once a macro is undefined, named tracing of that macro is lost. On the other hand, when GNUm4 encounterstraceon withoutarguments, it turns tracing on for all existing definitions at the time,but does not trace future definitions;traceoff without argumentsturns tracing off for all definitions regardless of whether they werealso traced by name; and tracing by name, such as with-tfoo atthe command line or traceon(`foo') in the input, is an attributethat is preserved even if the macro is currently undefined.

    Additionally, while POSIX requires trace output, it makes nodemands on the formatting of that output. Parsing trace output is notguaranteed to be reliable, even between different releases ofGNU M4; however, the intent is that any future changes intrace output will only occur under the direction of additionaldebugmode flags (seeDebug Levels).

  • POSIX requires eval (see Eval) to treat alloperators with the same precedence as C. However, earlier versions ofGNUm4 followed the traditional behavior of otherm4 implementations, where bitwise and logical negation (‘~’and ‘!’) have lower precedence than equality operators; and whereequality operators (‘==’ and ‘!=’) had the same precedence asrelational operators (such as ‘<’). Use explicit parentheses toensure proper precedence. As extensions to POSIX,GNU m4 gives well-defined semantics to operations thatC leaves undefined, such as when overflow occurs, when shifting negativenumbers, or when performing division by zero. POSIX alsorequires ‘=’ to cause an error, but many traditionalimplementations allowed it as an alias for ‘==’.
  • POSIX 2001 requires translit (see Translit) totreat each character of the second and third arguments literally. However, it is anticipated that the next version of POSIX willallow the GNUm4 behavior of treating ‘-’ as arange operator.
  • POSIX requires m4 to honor the locale environmentvariables of LANG, LC_ALL,LC_CTYPE,LC_MESSAGES, andNLSPATH, but this has not yet beenimplemented in GNUm4.
  • POSIX states that only unquoted leading newlines and blanks(that is, space and tab) are ignored when collecting macro arguments. However, this appears to be a bug in POSIX, since mosttraditional implementations also ignore all whitespace (formfeed,carriage return, and vertical tab). GNU m4 followstradition and ignores all leading unquoted whitespace.
  • A strictly-compliant POSIX client is not allowed to usecommand-line arguments not specified by POSIX. However, sincethis version of M4 ignoresPOSIXLY_CORRECT and enables the option--gnu by default (seeInvoking m4), aclient desiring to be strictly compliant has no way to disableGNU extensions that conflict with POSIX whendirectly invoking the compiledm4. A future version ofGNU M4 will honor the environment variablePOSIXLY_CORRECT,implicitly enabling --traditional if it is set, in order toallow a strictly-compliant client. In the meantime, a client needingstrict POSIX compliance can use the workaround of invoking ashell script wrapper, where the wrapper then adds --traditionalto the arguments passed to the compiledm4.


Previous:  Incompatibilities,Up:  Compatibility

16.3 Other incompatibilities

There are a few other incompatibilities between this implementation ofm4, and the System V version.

  • GNU m4 implements sync lines differently from System Vm4, when text is being diverted. GNUm4 outputsthe sync lines when the text is being diverted, and System Vm4when the diverted text is being brought back.

    The problem is which lines and file names should be attached to textthat is being, or has been, diverted. System Vm4 regards allthe diverted text as being generated by the source line containing theundivert call, whereas GNUm4 regards thediverted text as being generated at the time it is diverted.

    The sync line option is used mostly when using m4 asa front end to a compiler. If a diverted line causes a compiler error,the error messages should most probably refer to the place where thediversion was made, and not where it was inserted again.

              divert(2)2
              divert(1)1
              divert`'0
              ⇒#line 3 "stdin"
              ⇒0
              ^D
              ⇒#line 2 "stdin"
              ⇒1
              ⇒#line 1 "stdin"
              ⇒2
    

    The current m4 implementation has a limitation that the synclineoutput at the start of each diversion occurs no matter what, even if theprevious diversion did not end with a newline. This goes contrary tothe claim that synclines appear on a line by themselves, so thislimitation may be corrected in a future version of m4. In themeantime, when using -s, it is wisest to make sure alldiversions end with newline.

  • GNU m4 makes no attempt at prohibiting self-referentialdefinitions like:
              define(`x', `x')
              ⇒
              define(`x', `x ')
              ⇒
    

    There is nothing inherently wrong with defining ‘x’ toreturn ‘x’. The wrong thing is to expand ‘x’ unquoted,because that would cause an infinite rescan loop. In m4, one might use macros to hold strings, as we do forvariables in other programming languages, further checking them with:

              ifelse(defn(`holder'), `value', ...)
    

    In cases like this one, an interdiction for a macro to hold its own namewould be a useless limitation. Of course, this leaves more rope for theGNUm4 user to hang himself! Rescanning hangs may beavoided through careful programming, a little like for endless loops intraditional programming languages.


Next:  ,Previous:  Compatibility,Up:  Top

17 Correct version of some examples

Some of the examples in this manuals are buggy or not very robust, fordemonstration purposes. Improved versions of these composite macros arepresented here.


Next:  ,Up:  Answers

17.1 Solution for exch

The exch macro (see Arguments) as presented requires clientsto double quote their arguments. A nicer definition, which letsclients follow the rule of thumb of one level of quoting per level ofparentheses, involves adding quotes in the definition of exch, asfollows:

     define(`exch', ``$2', `$1'')
     ⇒
     define(exch(`expansion text', `macro'))
     ⇒
     macro
     ⇒expansion text


Next:  ,Previous:  Improved exch,Up:  Answers

17.2 Solution for forloop

The forloop macro (see Forloop) as presented earlier can gointo an infinite loop if given an iterator that is not parsed as a macroname. It does not do any sanity checking on its numeric bounds, andonly permits decimal numbers for bounds. Here is an improved version,shipped as m4-1.4.16/examples/forloop2.m4; thisversion also optimizes overhead by calling four macros instead of sixper iteration (excluding those intext), by not dereferencing theiterator in the helper _forloop.

     $ m4 -d -I examples
     undivert(`forloop2.m4')dnl
     ⇒divert(`-1')
     ⇒# forloop(var, from, to, stmt) - improved version:
     ⇒#   works even if VAR is not a strict macro name
     ⇒#   performs sanity check that FROM is larger than TO
     ⇒#   allows complex numerical expressions in TO and FROM
     ⇒define(`forloop', `ifelse(eval(`($2) <= ($3)'), `1',
     ⇒  `pushdef(`$1')_$0(`$1', eval(`$2'),
     ⇒    eval(`$3'), `$4')popdef(`$1')')')
     ⇒define(`_forloop',
     ⇒  `define(`$1', `$2')$4`'ifelse(`$2', `$3', `',
     ⇒    `$0(`$1', incr(`$2'), `$3', `$4')')')
     ⇒divert`'dnl
     include(`forloop2.m4')
     ⇒
     forloop(`i', `2', `1', `no iteration occurs')
     ⇒
     forloop(`', `1', `2', ` odd iterator name')
     ⇒ odd iterator name odd iterator name
     forloop(`i', `5 + 5', `0xc', ` 0x`'eval(i, `16')')
     ⇒ 0xa 0xb 0xc
     forloop(`i', `a', `b', `non-numeric bounds')
     error-->m4:stdin:6: bad expression in eval (bad input): (a) <= (b)
     ⇒

One other change to notice is that the improved version used ‘_$0’rather than ‘_foreach’ to invoke the helper routine. In general,this is a good practice to follow, because then the set of macros can beuniformly transformed. The following example shows a transformationthat doubles the current quoting and appends a suffix ‘2’ to eachtransformed macro. Ifforeach refers to the literal‘_foreach’, thenforeach2 invokes _foreach instead ofthe intended _foreach2, and the mixing of quoting paradigms leadsto an infinite recursion loop in this example.

     $ m4 -d -L 9 -I examples
     define(`arg1', `$1')include(`forloop2.m4')include(`quote.m4')
     ⇒
     define(`double', `define(`$1'`2',
       arg1(patsubst(dquote(defn(`$1')), `[`']', `\&\&')))')
     ⇒
     double(`forloop')double(`_forloop')defn(`forloop2')
     ⇒ifelse(eval(``($2) <= ($3)''), ``1'',
     ⇒  ``pushdef(``$1'')_$0(``$1'', eval(``$2''),
     ⇒    eval(``$3''), ``$4'')popdef(``$1'')'')
     forloop(i, 1, 5, `ifelse(')forloop(i, 1, 5, `)')
     ⇒
     changequote(`[', `]')changequote([``], [''])
     ⇒
     forloop2(i, 1, 5, ``ifelse('')forloop2(i, 1, 5, ``)'')
     ⇒
     changequote`'include(`forloop.m4')
     ⇒
     double(`forloop')double(`_forloop')defn(`forloop2')
     ⇒pushdef(``$1'', ``$2'')_forloop($@)popdef(``$1'')
     forloop(i, 1, 5, `ifelse(')forloop(i, 1, 5, `)')
     ⇒
     changequote(`[', `]')changequote([``], [''])
     ⇒
     forloop2(i, 1, 5, ``ifelse('')forloop2(i, 1, 5, ``)'')
     error-->m4:stdin:12: recursion limit of 9 exceeded, use -L<N> to change it

One more optimization is still possible. Instead of repeatedlyassigning a variable then invoking or dereferencing it, it is possibleto pass the current iterator value as a single argument. Coupled withcurry if other arguments are needed (seeComposition), orwith helper macros if the argument is needed in more than one place inthe expansion, the output can be generated with three, rather than four,macros of overhead per iteration. Notice how the filem4-1.4.16/examples/forloop3.m4 rearranges thearguments of the helper _forloop to take two arguments that areplaced around the current value. By splitting a balanced set ofparantheses across multiple arguments, the helper macro can now beshared byforloop and the new forloop_arg.

     $ m4 -I examples
     include(`forloop3.m4')
     ⇒
     undivert(`forloop3.m4')dnl
     ⇒divert(`-1')
     ⇒# forloop_arg(from, to, macro) - invoke MACRO(value) for
     ⇒#   each value between FROM and TO, without define overhead
     ⇒define(`forloop_arg', `ifelse(eval(`($1) <= ($2)'), `1',
     ⇒  `_forloop(`$1', eval(`$2'), `$3(', `)')')')
     ⇒# forloop(var, from, to, stmt) - refactored to share code
     ⇒define(`forloop', `ifelse(eval(`($2) <= ($3)'), `1',
     ⇒  `pushdef(`$1')_forloop(eval(`$2'), eval(`$3'),
     ⇒    `define(`$1',', `)$4')popdef(`$1')')')
     ⇒define(`_forloop',
     ⇒  `$3`$1'$4`'ifelse(`$1', `$2', `',
     ⇒    `$0(incr(`$1'), `$2', `$3', `$4')')')
     ⇒divert`'dnl
     forloop(`i', `1', `3', ` i')
     ⇒ 1 2 3
     define(`echo', `$@')
     ⇒
     forloop_arg(`1', `3', ` echo')
     ⇒ 1 2 3
     include(`curry.m4')
     ⇒
     forloop_arg(`1', `3', `curry(`pushdef', `a')')
     ⇒
     a
     ⇒3
     popdef(`a')a
     ⇒2
     popdef(`a')a
     ⇒1
     popdef(`a')a
     ⇒a

Of course, it is possible to make even more improvements, such asadding an optional step argument, or allowing iteration throughdescending sequences. GNU Autoconf provides some of theseadditional bells and whistles in itsm4_for macro.


Next:  ,Previous:  Improved forloop,Up:  Answers

17.3 Solution for foreach

The foreach and foreachq macros (see Foreach) aspresented earlier each have flaws. First, we will examine and fix thequadratic behavior offoreachq:

     $ m4 -I examples
     include(`foreachq.m4')
     ⇒
     traceon(`shift')debugmode(`aq')
     ⇒
     foreachq(`x', ``1', `2', `3', `4'', `x
     ')dnl
     ⇒1
     error-->m4trace: -3- shift(`1', `2', `3', `4')
     error-->m4trace: -2- shift(`1', `2', `3', `4')
     ⇒2
     error-->m4trace: -4- shift(`1', `2', `3', `4')
     error-->m4trace: -3- shift(`2', `3', `4')
     error-->m4trace: -3- shift(`1', `2', `3', `4')
     error-->m4trace: -2- shift(`2', `3', `4')
     ⇒3
     error-->m4trace: -5- shift(`1', `2', `3', `4')
     error-->m4trace: -4- shift(`2', `3', `4')
     error-->m4trace: -3- shift(`3', `4')
     error-->m4trace: -4- shift(`1', `2', `3', `4')
     error-->m4trace: -3- shift(`2', `3', `4')
     error-->m4trace: -2- shift(`3', `4')
     ⇒4
     error-->m4trace: -6- shift(`1', `2', `3', `4')
     error-->m4trace: -5- shift(`2', `3', `4')
     error-->m4trace: -4- shift(`3', `4')
     error-->m4trace: -3- shift(`4')

Each successive iteration was adding more quotedshiftinvocations, and the entire list contents were passing through everyiteration. In general, when recursing, it is a good idea to make therecursion use fewer arguments, rather than adding additional quoteduses ofshift. By doing so, m4 uses less memory, invokesfewer macros, is less likely to run into machine limits, and mostimportantly, performs faster. The fixed version offoreachq canbe found in m4-1.4.16/examples/foreachq2.m4:

     $ m4 -I examples
     include(`foreachq2.m4')
     ⇒
     undivert(`foreachq2.m4')dnl
     ⇒include(`quote.m4')dnl
     ⇒divert(`-1')
     ⇒# foreachq(x, `item_1, item_2, ..., item_n', stmt)
     ⇒#   quoted list, improved version
     ⇒define(`foreachq', `pushdef(`$1')_$0($@)popdef(`$1')')
     ⇒define(`_arg1q', ``$1'')
     ⇒define(`_rest', `ifelse(`$#', `1', `', `dquote(shift($@))')')
     ⇒define(`_foreachq', `ifelse(`$2', `', `',
     ⇒  `define(`$1', _arg1q($2))$3`'$0(`$1', _rest($2), `$3')')')
     ⇒divert`'dnl
     traceon(`shift')debugmode(`aq')
     ⇒
     foreachq(`x', ``1', `2', `3', `4'', `x
     ')dnl
     ⇒1
     error-->m4trace: -3- shift(`1', `2', `3', `4')
     ⇒2
     error-->m4trace: -3- shift(`2', `3', `4')
     ⇒3
     error-->m4trace: -3- shift(`3', `4')
     ⇒4

Note that the fixed version calls unquoted helper macros in_foreachq to trim elements immediately; those helper macrosin turn must re-supply the layer of quotes lost in the macro invocation. Contrast the use of_arg1q, which quotes the first listelement, with _arg1 of the earlier implementation thatreturned the first list element directly. Additionally, by calling thehelper method immediately, the ‘defn(`iterator')’ no longercontains unexpanded macros.

The astute m4 programmer might notice that the solution above still usesmore memory and macro invocations, and thus more time, than strictlynecessary. Note that ‘$2’, which contains an arbitrarily longquoted list, is expanded and rescanned three times per iteration of_foreachq. Furthermore, every iteration of the algorithmeffectively unboxes then reboxes the list, which costs a couple of macroinvocations. It is possible to rewrite the algorithm for a bit morespeed by swapping the order of the arguments to _foreachq inorder to operate on an unboxed list in the first place, and by using thefixed-length ‘$#’ instead of an arbitrary length list as the key toend recursion. The result is an overhead of six macro invocations perloop (excluding any macros intext), instead of eight. Thisalternative approach is available asm4-1.4.16/examples/foreach3.m4:

     $ m4 -I examples
     include(`foreachq3.m4')
     ⇒
     undivert(`foreachq3.m4')dnl
     ⇒divert(`-1')
     ⇒# foreachq(x, `item_1, item_2, ..., item_n', stmt)
     ⇒#   quoted list, alternate improved version
     ⇒define(`foreachq', `ifelse(`$2', `', `',
     ⇒  `pushdef(`$1')_$0(`$1', `$3', `', $2)popdef(`$1')')')
     ⇒define(`_foreachq', `ifelse(`$#', `3', `',
     ⇒  `define(`$1', `$4')$2`'$0(`$1', `$2',
     ⇒    shift(shift(shift($@))))')')
     ⇒divert`'dnl
     traceon(`shift')debugmode(`aq')
     ⇒
     foreachq(`x', ``1', `2', `3', `4'', `x
     ')dnl
     ⇒1
     error-->m4trace: -4- shift(`x', `x
     error-->', `', `1', `2', `3', `4')
     error-->m4trace: -3- shift(`x
     error-->', `', `1', `2', `3', `4')
     error-->m4trace: -2- shift(`', `1', `2', `3', `4')
     ⇒2
     error-->m4trace: -4- shift(`x', `x
     error-->', `1', `2', `3', `4')
     error-->m4trace: -3- shift(`x
     error-->', `1', `2', `3', `4')
     error-->m4trace: -2- shift(`1', `2', `3', `4')
     ⇒3
     error-->m4trace: -4- shift(`x', `x
     error-->', `2', `3', `4')
     error-->m4trace: -3- shift(`x
     error-->', `2', `3', `4')
     error-->m4trace: -2- shift(`2', `3', `4')
     ⇒4
     error-->m4trace: -4- shift(`x', `x
     error-->', `3', `4')
     error-->m4trace: -3- shift(`x
     error-->', `3', `4')
     error-->m4trace: -2- shift(`3', `4')

In the current version of M4, every instance of ‘$@’ is rescannedas it is encountered. Thus, theforeachq3.m4 alternative usesmuch less memory thanforeachq2.m4, and executes as much as 10%faster, since each iteration encounters fewer ‘$@’. However, theimplementation of rescanning every byte in ‘$@’ is quadratic inthe number of bytes scanned (for example, making the broken version inforeachq.m4 cubic, rather than quadratic, in behavior). A futurerelease of M4 will improve the underlying implementation by reusingresults of previous scans, so that both styles of foreachq canbecome linear in the number of bytes scanned. Notice how theimplementation injects an empty argument prior to expanding ‘$2’withinforeachq; the helper macro _foreachq then ignoresthe third argument altogether, and ends recursion when there are threearguments left because there was nothing left to pass throughshift. Thus, each iteration only needs one ifelse, ratherthan the two conditionals used in the version fromforeachq2.m4.

So far, all of the implementations offoreachq presented havebeen quadratic with M4 1.4.x. But forloop is linear, becauseeach iteration parses a constant amount of arguments. So, it ispossible to design a variant that usesforloop to do theiteration, then uses ‘$@’ only once at the end, giving a linearresult even with older M4 implementations. This implementation relieson the GNU extension that ‘$10’ expands to the tenthargument rather than the first argument concatenated with ‘0’. Thetrick is to define an intermediate macro that repeats the textm4_define(`$1', `$n')$2`', with ‘n’ set to successiveintegers corresponding to each argument. The helper macro_foreachq_ is needed in order to generate the literal sequencessuch as ‘$1’ into the intermediate macro, rather than expandingthem as the arguments of _foreachq. With this approach, noshift calls are even needed! Even though there are seven macrosof overhead per iteration instead of six inforeachq3.m4, thelinear scaling is apparent at relatively small list sizes. However,this approach will need adjustment when a future version of M4 followsPOSIX by no longer treating ‘$10’ as the tenth argument;the anticipation is that ‘${10}’ can be used instead, althoughthat alternative syntax is not yet supported.

     $ m4 -I examples
     include(`foreachq4.m4')
     ⇒
     undivert(`foreachq4.m4')dnl
     ⇒include(`forloop2.m4')dnl
     ⇒divert(`-1')
     ⇒# foreachq(x, `item_1, item_2, ..., item_n', stmt)
     ⇒#   quoted list, version based on forloop
     ⇒define(`foreachq',
     ⇒`ifelse(`$2', `', `', `_$0(`$1', `$3', $2)')')
     ⇒define(`_foreachq',
     ⇒`pushdef(`$1', forloop(`$1', `3', `$#',
     ⇒  `$0_(`1', `2', indir(`$1'))')`popdef(
     ⇒    `$1')')indir(`$1', $@)')
     ⇒define(`_foreachq_',
     ⇒``define(`$$1', `$$3')$$2`''')
     ⇒divert`'dnl
     traceon(`shift')debugmode(`aq')
     ⇒
     foreachq(`x', ``1', `2', `3', `4'', `x
     ')dnl
     ⇒1
     ⇒2
     ⇒3
     ⇒4

For yet another approach, the improved version of foreach,available inm4-1.4.16/examples/foreach2.m4, simplyoverquotes the arguments to_foreach to begin with, usingdquote_elt. Then _foreach can just use_arg1 to remove the extra layer of quoting that was added upfront:

     $ m4 -I examples
     include(`foreach2.m4')
     ⇒
     undivert(`foreach2.m4')dnl
     ⇒include(`quote.m4')dnl
     ⇒divert(`-1')
     ⇒# foreach(x, (item_1, item_2, ..., item_n), stmt)
     ⇒#   parenthesized list, improved version
     ⇒define(`foreach', `pushdef(`$1')_$0(`$1',
     ⇒  (dquote(dquote_elt$2)), `$3')popdef(`$1')')
     ⇒define(`_arg1', `$1')
     ⇒define(`_foreach', `ifelse(`$2', `(`')', `',
     ⇒  `define(`$1', _arg1$2)$3`'$0(`$1', (dquote(shift$2)), `$3')')')
     ⇒divert`'dnl
     traceon(`shift')debugmode(`aq')
     ⇒
     foreach(`x', `(`1', `2', `3', `4')', `x
     ')dnl
     error-->m4trace: -4- shift(`1', `2', `3', `4')
     error-->m4trace: -4- shift(`2', `3', `4')
     error-->m4trace: -4- shift(`3', `4')
     ⇒1
     error-->m4trace: -3- shift(``1'', ``2'', ``3'', ``4'')
     ⇒2
     error-->m4trace: -3- shift(``2'', ``3'', ``4'')
     ⇒3
     error-->m4trace: -3- shift(``3'', ``4'')
     ⇒4
     error-->m4trace: -3- shift(``4'')

It is likewise possible to write a variant of foreach thatperforms in linear time on M4 1.4.x; the easiest method is probablywriting a version offoreach that unboxes its list, then invokes_foreachq as previously defined inforeachq4.m4.

In summary, recursion over list elements is trickier than it appeared atfirst glance, but provides a powerful idiom withinm4 processing. As a final demonstration, both list styles are now able to handleseveral scenarios that would wreak havoc on one or both of the originalimplementations. This points out one other difference between thelist styles.foreach evaluates unquoted list elements only once,in preparation for calling_foreach, similary forforeachq as provided by foreachq3.m4 orforeachq4.m4. Butforeachq, as provided byforeachq2.m4,evaluates unquoted list elements twice while visiting the first listelement, once in_arg1q and once in _rest. Whendeciding which list style to use, one must take into account whetherrepeating the side effects of unquoted list elements will have anydetrimental effects.

     $ m4 -I examples
     include(`foreach2.m4')
     ⇒
     include(`foreachq2.m4')
     ⇒
     dnl 0-element list:
     foreach(`x', `', `<x>') / foreachq(`x', `', `<x>')
     ⇒ / 
     dnl 1-element list of empty element
     foreach(`x', `()', `<x>') / foreachq(`x', ``'', `<x>')
     ⇒<> / <>
     dnl 2-element list of empty elements
     foreach(`x', `(`',`')', `<x>') / foreachq(`x', ``',`'', `<x>')
     ⇒<><> / <><>
     dnl 1-element list of a comma
     foreach(`x', `(`,')', `<x>') / foreachq(`x', ``,'', `<x>')
     ⇒<,> / <,>
     dnl 2-element list of unbalanced parentheses
     foreach(`x', `(`(', `)')', `<x>') / foreachq(`x', ``(', `)'', `<x>')
     ⇒<(><)> / <(><)>
     define(`ab', `oops')dnl using defn(`iterator')
     foreach(`x', `(`a', `b')', `defn(`x')') /dnl
      foreachq(`x', ``a', `b'', `defn(`x')')
     ⇒ab / ab
     define(`active', `ACT, IVE')
     ⇒
     traceon(`active')
     ⇒
     dnl list of unquoted macros; expansion occurs before recursion
     foreach(`x', `(active, active)', `<x>
     ')dnl
     error-->m4trace: -4- active -> `ACT, IVE'
     error-->m4trace: -4- active -> `ACT, IVE'
     ⇒<ACT>
     ⇒<IVE>
     ⇒<ACT>
     ⇒<IVE>
     foreachq(`x', `active, active', `<x>
     ')dnl
     error-->m4trace: -3- active -> `ACT, IVE'
     error-->m4trace: -3- active -> `ACT, IVE'
     ⇒<ACT>
     error-->m4trace: -3- active -> `ACT, IVE'
     error-->m4trace: -3- active -> `ACT, IVE'
     ⇒<IVE>
     ⇒<ACT>
     ⇒<IVE>
     dnl list of quoted macros; expansion occurs during recursion
     foreach(`x', `(`active', `active')', `<x>
     ')dnl
     error-->m4trace: -1- active -> `ACT, IVE'
     ⇒<ACT, IVE>
     error-->m4trace: -1- active -> `ACT, IVE'
     ⇒<ACT, IVE>
     foreachq(`x', ``active', `active'', `<x>
     ')dnl
     error-->m4trace: -1- active -> `ACT, IVE'
     ⇒<ACT, IVE>
     error-->m4trace: -1- active -> `ACT, IVE'
     ⇒<ACT, IVE>
     dnl list of double-quoted macro names; no expansion
     foreach(`x', `(``active'', ``active'')', `<x>
     ')dnl
     ⇒<active>
     ⇒<active>
     foreachq(`x', ```active'', ``active''', `<x>
     ')dnl
     ⇒<active>
     ⇒<active>


Next:  ,Previous:  Improved foreach,Up:  Answers

17.4 Solution for copy

The macro copy presented aboveis unable to handle builtin tokens with M4 1.4.x, because it tries topass the builtin token through the macrocurry, where it issilently flattened to an empty string (see Composition). Ratherthan using the problematic curry to work around the limitationthatstack_foreach expects to invoke a macro that takes exactlyone argument, we can write a new macro that lets us form the exacttwo-argumentpushdef call sequence needed, so that we are nolonger passing a builtin token through a text macro.

— Composite: stack_foreach_sep ( macro, pre, post, sep)
— Composite: stack_foreach_sep_lifo ( macro, pre, post, sep)

For each of the pushdef definitions associated with macro,expand the sequence ‘pre`'definition`'post’. Additionally, expandsep between definitions. stack_foreach_sep visits the oldest definition first, whilestack_foreach_sep_lifo visits the current definition first. Theexpansion may dereferencemacro, but should not modify it. Thereare a few special macros, such asdefn, which cannot be used asthe macro parameter.

Note that stack_foreach(`macro', `action') isequivalent tostack_foreach_sep(`macro', `action(',`)'). By supplying explicit parentheses, split among thepre andpost arguments to stack_foreach_sep, it is now possible toconstruct macro calls with more than one argument, without passingbuiltin tokens through a macro call. It is likewise possible todirectly reference the stack definitions without a macro call, byleaving pre and post empty. Thus, in addition to fixingcopy on builtin tokens, it also executes with fewer macroinvocations.

The new macro also adds a separator that is only output after the firstiteration of the helper_stack_reverse_sep, implemented byprepending the original sep topre and omitting a separgument in subsequent iterations. Note that the empty string thatseparatessep from pre is provided as part of the fourthargument when originally calling_stack_reverse_sep, and not bywriting $4`'$3 as the third argument in the recursive call; whilethe other approach would give the same output, it does so at the expenseof increasing the argument size on each iteration of_stack_reverse_sep, which results in quadratic instead of linearexecution time. The improved stack walking macros are available inm4-1.4.16/examples/stack_sep.m4:

     $ m4 -I examples
     include(`stack_sep.m4')
     ⇒
     define(`copy', `ifdef(`$2', `errprint(`$2 already defined
     ')m4exit(`1')',
        `stack_foreach_sep(`$1', `pushdef(`$2',', `)')')')dnl
     pushdef(`a', `1')pushdef(`a', defn(`divnum'))
     ⇒
     copy(`a', `b')
     ⇒
     b
     ⇒0
     popdef(`b')
     ⇒
     b
     ⇒1
     pushdef(`c', `1')pushdef(`c', `2')
     ⇒
     stack_foreach_sep_lifo(`c', `', `', `, ')
     ⇒2, 1
     undivert(`stack_sep.m4')dnl
     ⇒divert(`-1')
     ⇒# stack_foreach_sep(macro, pre, post, sep)
     ⇒# Invoke PRE`'defn`'POST with a single argument of each definition
     ⇒# from the definition stack of MACRO, starting with the oldest, and
     ⇒# separated by SEP between definitions.
     ⇒define(`stack_foreach_sep',
     ⇒`_stack_reverse_sep(`$1', `tmp-$1')'dnl
     ⇒`_stack_reverse_sep(`tmp-$1', `$1', `$2`'defn(`$1')$3', `$4`'')')
     ⇒# stack_foreach_sep_lifo(macro, pre, post, sep)
     ⇒# Like stack_foreach_sep, but starting with the newest definition.
     ⇒define(`stack_foreach_sep_lifo',
     ⇒`_stack_reverse_sep(`$1', `tmp-$1', `$2`'defn(`$1')$3', `$4`'')'dnl
     ⇒`_stack_reverse_sep(`tmp-$1', `$1')')
     ⇒define(`_stack_reverse_sep',
     ⇒`ifdef(`$1', `pushdef(`$2', defn(`$1'))$3`'popdef(`$1')$0(
     ⇒  `$1', `$2', `$4$3')')')
     ⇒divert`'dnl


Next:  ,Previous:  Improved copy,Up:  Answers

17.5 Solution for m4wrap

The replacement m4wrap versions presented above, designed toguarantee FIFO or LIFO order regardless of the underlying M4implementation, share a bug when dealing with wrapped text that lookslike parameter expansion. Note how the invocation ofm4wrapn interprets these parameters, while using thebuiltin preserves them for their intended use.

     $ m4 -I examples
     include(`wraplifo.m4')
     ⇒
     m4wrap(`define(`foo', ``$0:'-$1-$*-$#-')foo(`a', `b')
     ')
     ⇒
     builtin(`m4wrap', ``'define(`bar', ``$0:'-$1-$*-$#-')bar(`a', `b')
     ')
     ⇒
     ^D
     ⇒bar:-a-a,b-2-
     ⇒m4wrap0:---0-

Additionally, the computation of _m4wrap_level and creation ofmultiplem4wrapn placeholders in the original examples ismore expensive in time and memory than strictly necessary. Notice howthe improved version grabs the wrapped text viadefn to avoidparameter expansion, then undefines _m4wrap_text, beforestripping a level of quotes with_arg1 to expand the text. Thatway, each level of wrapping reuses the single placeholder, which startseach nesting level in an undefined state.

Finally, it is worth emulating the GNU M4 extension of savingall arguments to m4wrap, separated by a space, rather than savingjust the first argument. This is done with thejoin macrodocumented previously (see Shift). The improved LIFO example isshipped asm4-1.4.16/examples/wraplifo2.m4, and caneasily be converted to a FIFO solution by swapping the adjacentinvocations ofjoinall and defn.

     $ m4 -I examples
     include(`wraplifo2.m4')
     ⇒
     undivert(`wraplifo2.m4')dnl
     ⇒dnl Redefine m4wrap to have LIFO semantics, improved example.
     ⇒include(`join.m4')dnl
     ⇒define(`_m4wrap', defn(`m4wrap'))dnl
     ⇒define(`_arg1', `$1')dnl
     ⇒define(`m4wrap',
     ⇒`ifdef(`_$0_text',
     ⇒       `define(`_$0_text', joinall(` ', $@)defn(`_$0_text'))',
     ⇒       `_$0(`_arg1(defn(`_$0_text')undefine(`_$0_text'))')dnl
     ⇒define(`_$0_text', joinall(` ', $@))')')dnl
     m4wrap(`define(`foo', ``$0:'-$1-$*-$#-')foo(`a', `b')
     ')
     ⇒
     m4wrap(`lifo text
     m4wrap(`nested', `', `$@
     ')')
     ⇒
     ^D
     ⇒lifo text
     ⇒foo:-a-a,b-2-
     ⇒nested  $@


Next:  ,Previous:  Improved m4wrap,Up:  Answers

17.6 Solution for cleardivert

The cleardivert macro (see Cleardivert) cannot, as it stands, becalled without arguments to clear all pending diversions. That isbecause using undivert with an empty string for an argument is differentthan using it with no arguments at all. Compare the earlier definitionwith one that takes the number of arguments into account:

     define(`cleardivert',
       `pushdef(`_n', divnum)divert(`-1')undivert($@)divert(_n)popdef(`_n')')
     ⇒
     divert(`1')one
     divert
     ⇒
     cleardivert
     ⇒
     undivert
     ⇒one
     ⇒
     define(`cleardivert',
       `pushdef(`_num', divnum)divert(`-1')ifelse(`$#', `0',
         `undivert`'', `undivert($@)')divert(_num)popdef(`_num')')
     ⇒
     divert(`2')two
     divert
     ⇒
     cleardivert
     ⇒
     undivert
     ⇒

17.7 Solution for capitalize

The capitalize macro (see Patsubst) as presented earlier doesnot allow clients to follow the quoting rule of thumb. Consider thethree macrosactive, Active, and ACTIVE, and thedifference between callingcapitalize with the expansion of amacro, expanding the result of a case change, and changing the case of adouble-quoted string:

     $ m4 -I examples
     include(`capitalize.m4')dnl
     define(`active', `act1, ive')dnl
     define(`Active', `Act2, Ive')dnl
     define(`ACTIVE', `ACT3, IVE')dnl
     upcase(active)
     ⇒ACT1,IVE
     upcase(`active')
     ⇒ACT3, IVE
     upcase(``active'')
     ⇒ACTIVE
     downcase(ACTIVE)
     ⇒act3,ive
     downcase(`ACTIVE')
     ⇒act1, ive
     downcase(``ACTIVE'')
     ⇒active
     capitalize(active)
     ⇒Act1
     capitalize(`active')
     ⇒Active
     capitalize(``active'')
     ⇒_capitalize(`active')
     define(`A', `OOPS')
     ⇒
     capitalize(active)
     ⇒OOPSct1
     capitalize(`active')
     ⇒OOPSctive

First, when capitalize is called with more than one argument, itwas throwing away later arguments, whereasupcase anddowncase used ‘$*’ to collect them all. The fix is simple:use ‘$*’ consistently.

Next, with single-quoting, capitalize outputs a single character,a set of quotes, then the rest of the characters, making it impossibleto invokeActive after the fact, and allowing the alternate macroA to interfere. Here, the solution is to use additional quotingin the helper macros, then pass the final over-quoted output stringthrough_arg1 to remove the extra quoting and finally invoke theconcatenated portions as a single string.

Finally, when passed a double-quoted string, the nested macro_capitalize is never invoked because it ended up nested insidequotes. This one is the toughest to fix. In short, we have no idea howmany levels of quotes are in effect on the substring being altered bypatsubst. If the replacement string cannot be expressed entirelyin terms of literal text and backslash substitutions, then we need amechanism to guarantee that the helper macros are invoked outside ofquotes. In other words, this sounds like a job for changequote(see Changequote). By changing the active quoting characters, wecan guarantee that replacement text injected bypatsubst alwaysoccurs in the middle of a string that has exactly one level ofover-quoting using alternate quotes; so the replacement text closes thequoted string, invokes the helper macros, then reopens the quotedstring. In turn, that means the replacement text has unbalanced quotes,necessitating another round of changequote.

In the fixed version below, (also shipped asm4-1.4.16/examples/capitalize2.m4),capitalizeuses the alternate quotes of ‘<<[’ and ‘]>>’ (the longerstrings are chosen so as to be less likely to appear in the text beingconverted). The helpers_to_alt and _from_alt merelyreduce the number of characters required to perform achangequote, since the definition changes twice. The outermostpair means thatpatsubst and _capitalize_alt are invokedwith alternate quoting; the innermost pair is used so that the thirdargument topatsubst can contain an unbalanced‘]>>’/‘<<[’ pair. Note thatupcase and downcasemust be redefined as _upcase_alt and_downcase_alt, sincethey contain nested quotes but are invoked with the alternate quotingscheme in effect.

     $ m4 -I examples
     include(`capitalize2.m4')dnl
     define(`active', `act1, ive')dnl
     define(`Active', `Act2, Ive')dnl
     define(`ACTIVE', `ACT3, IVE')dnl
     define(`A', `OOPS')dnl
     capitalize(active; `active'; ``active''; ```actIVE''')
     ⇒Act1,Ive; Act2, Ive; Active; `Active'
     undivert(`capitalize2.m4')dnl
     ⇒divert(`-1')
     ⇒# upcase(text)
     ⇒# downcase(text)
     ⇒# capitalize(text)
     ⇒#   change case of text, improved version
     ⇒define(`upcase', `translit(`$*', `a-z', `A-Z')')
     ⇒define(`downcase', `translit(`$*', `A-Z', `a-z')')
     ⇒define(`_arg1', `$1')
     ⇒define(`_to_alt', `changequote(`<<[', `]>>')')
     ⇒define(`_from_alt', `changequote(<<[`]>>, <<[']>>)')
     ⇒define(`_upcase_alt', `translit(<<[$*]>>, <<[a-z]>>, <<[A-Z]>>)')
     ⇒define(`_downcase_alt', `translit(<<[$*]>>, <<[A-Z]>>, <<[a-z]>>)')
     ⇒define(`_capitalize_alt',
     ⇒  `regexp(<<[$1]>>, <<[^\(\w\)\(\w*\)]>>,
     ⇒    <<[_upcase_alt(<<[<<[\1]>>]>>)_downcase_alt(<<[<<[\2]>>]>>)]>>)')
     ⇒define(`capitalize',
     ⇒  `_arg1(_to_alt()patsubst(<<[<<[$*]>>]>>, <<[\w+]>>,
     ⇒    _from_alt()`]>>_$0_alt(<<[\&]>>)<<['_to_alt())_from_alt())')
     ⇒divert`'dnl


Previous:  Improved capitalize,Up:  Answers

17.8 Solution for fatal_error

The fatal_error macro (see M4exit) is not robust to versionsof GNU M4 earlier than 1.4.8, where invoking__file__ (seeLocation) inside m4wrap would resultin an empty string, and__line__ resulted in ‘0’ eventhough all files start at line 1. Furthermore, versions earlier than1.4.6 did not support the__program__ macro. If you wantfatal_error to work across the entire 1.4.x release series, abetter implementation would be:

     define(`fatal_error',
       `errprint(ifdef(`__program__', `__program__', ``m4'')'dnl
     `:ifelse(__line__, `0', `',
         `__file__:__line__:')` fatal error: $*
     ')m4exit(`1')')
     ⇒
     m4wrap(`divnum(`demo of internal message')
     fatal_error(`inside wrapped text')')
     ⇒
     ^D
     error-->m4:stdin:6: Warning: excess arguments to builtin `divnum' ignored
     ⇒0
     error-->m4:stdin:6: fatal error: inside wrapped text


Next:  ,Previous:  Answers,Up:  Top

Appendix A How to make copies of the overall M4 package

This appendix covers the license for copying the source code of theoverall M4 package. This manual is under a different set ofrestrictions, covered later (seeCopying This Manual).

A.1 License for copying the M4 package

Version 3, 29 June 2007
     Copyright © 2007 Free Software Foundation, Inc. http://fsf.org/
     
     Everyone is permitted to copy and distribute verbatim copies of this
     license document, but changing it is not allowed.

Preamble

The GNU General Public License is a free, copyleft license forsoftware and other kinds of works.

The licenses for most software and other practical works are designedto take away your freedom to share and change the works. By contrast,the GNU General Public License is intended to guarantee your freedomto share and change all versions of a program—to make sure it remainsfree software for all its users. We, the Free Software Foundation,use the GNU General Public License for most of our software; itapplies also to any other work released this way by its authors. Youcan apply it to your programs, too.

When we speak of free software, we are referring to freedom, notprice. Our General Public Licenses are designed to make sure that youhave the freedom to distribute copies of free software (and charge forthem if you wish), that you receive source code or can get it if youwant it, that you can change the software or use pieces of it in newfree programs, and that you know you can do these things.

To protect your rights, we need to prevent others from denying youthese rights or asking you to surrender the rights. Therefore, youhave certain responsibilities if you distribute copies of thesoftware, or if you modify it: responsibilities to respect the freedomof others.

For example, if you distribute copies of such a program, whethergratis or for a fee, you must pass on to the recipients the samefreedoms that you received. You must make sure that they, too,receive or can get the source code. And you must show them theseterms so they know their rights.

Developers that use the GNU GPL protect your rights with two steps:(1) assert copyright on the software, and (2) offer you this Licensegiving you legal permission to copy, distribute and/or modify it.

For the developers' and authors' protection, the GPL clearly explainsthat there is no warranty for this free software. For both users' andauthors' sake, the GPL requires that modified versions be marked aschanged, so that their problems will not be attributed erroneously toauthors of previous versions.

Some devices are designed to deny users access to install or runmodified versions of the software inside them, although themanufacturer can do so. This is fundamentally incompatible with theaim of protecting users' freedom to change the software. Thesystematic pattern of such abuse occurs in the area of products forindividuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit thepractice for those products. If such problems arise substantially inother domains, we stand ready to extend this provision to thosedomains in future versions of the GPL, as needed to protect thefreedom of users.

Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use ofsoftware on general-purpose computers, but in those that do, we wishto avoid the special danger that patents applied to a free programcould make it effectively proprietary. To prevent this, the GPLassures that patents cannot be used to render the program non-free.

The precise terms and conditions for copying, distribution andmodification follow.

TERMS AND CONDITIONS

  1. Definitions.

    “This License” refers to version 3 of the GNU General Public License.

    “Copyright” also means copyright-like laws that apply to other kindsof works, such as semiconductor masks.

    “The Program” refers to any copyrightable work licensed under thisLicense. Each licensee is addressed as “you”. “Licensees” and“recipients” may be individuals or organizations.

    To “modify” a work means to copy from or adapt all or part of the workin a fashion requiring copyright permission, other than the making ofan exact copy. The resulting work is called a “modified version” ofthe earlier work or a work “based on” the earlier work.

    A “covered work” means either the unmodified Program or a work basedon the Program.

    To “propagate” a work means to do anything with it that, withoutpermission, would make you directly or secondarily liable forinfringement under applicable copyright law, except executing it on acomputer or modifying a private copy. Propagation includes copying,distribution (with or without modification), making available to thepublic, and in some countries other activities as well.

    To “convey” a work means any kind of propagation that enables otherparties to make or receive copies. Mere interaction with a userthrough a computer network, with no transfer of a copy, is notconveying.

    An interactive user interface displays “Appropriate Legal Notices” tothe extent that it includes a convenient and prominently visiblefeature that (1) displays an appropriate copyright notice, and (2)tells the user that there is no warranty for the work (except to theextent that warranties are provided), that licensees may convey thework under this License, and how to view a copy of this License. Ifthe interface presents a list of user commands or options, such as amenu, a prominent item in the list meets this criterion.

  2. Source Code.

    The “source code” for a work means the preferred form of the work formaking modifications to it. “Object code” means any non-source formof a work.

    A “Standard Interface” means an interface that either is an officialstandard defined by a recognized standards body, or, in the case ofinterfaces specified for a particular programming language, one thatis widely used among developers working in that language.

    The “System Libraries” of an executable work include anything, otherthan the work as a whole, that (a) is included in the normal form ofpackaging a Major Component, but which is not part of that MajorComponent, and (b) serves only to enable use of the work with thatMajor Component, or to implement a Standard Interface for which animplementation is available to the public in source code form. A“Major Component”, in this context, means a major essential component(kernel, window system, and so on) of the specific operating system(if any) on which the executable work runs, or a compiler used toproduce the work, or an object code interpreter used to run it.

    The “Corresponding Source” for a work in object code form means allthe source code needed to generate, install, and (for an executablework) run the object code and to modify the work, including scripts tocontrol those activities. However, it does not include the work'sSystem Libraries, or general-purpose tools or generally available freeprograms which are used unmodified in performing those activities butwhich are not part of the work. For example, Corresponding Sourceincludes interface definition files associated with source files forthe work, and the source code for shared libraries and dynamicallylinked subprograms that the work is specifically designed to require,such as by intimate data communication or control flow between thosesubprograms and other parts of the work.

    The Corresponding Source need not include anything that users canregenerate automatically from other parts of the Corresponding Source.

    The Corresponding Source for a work in source code form is that samework.

  3. Basic Permissions.

    All rights granted under this License are granted for the term ofcopyright on the Program, and are irrevocable provided the statedconditions are met. This License explicitly affirms your unlimitedpermission to run the unmodified Program. The output from running acovered work is covered by this License only if the output, given itscontent, constitutes a covered work. This License acknowledges yourrights of fair use or other equivalent, as provided by copyright law.

    You may make, run and propagate covered works that you do not convey,without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of havingthem make modifications exclusively for you, or provide you withfacilities for running those works, provided that you comply with theterms of this License in conveying all material for which you do notcontrol copyright. Those thus making or running the covered works foryou must do so exclusively on your behalf, under your direction andcontrol, on terms that prohibit them from making any copies of yourcopyrighted material outside their relationship with you.

    Conveying under any other circumstances is permitted solely under theconditions stated below. Sublicensing is not allowed; section 10makes it unnecessary.

  4. Protecting Users' Legal Rights From Anti-Circumvention Law.

    No covered work shall be deemed part of an effective technologicalmeasure under any applicable law fulfilling obligations under article11 of the WIPO copyright treaty adopted on 20 December 1996, orsimilar laws prohibiting or restricting circumvention of suchmeasures.

    When you convey a covered work, you waive any legal power to forbidcircumvention of technological measures to the extent suchcircumvention is effected by exercising rights under this License withrespect to the covered work, and you disclaim any intention to limitoperation or modification of the work as a means of enforcing, againstthe work's users, your or third parties' legal rights to forbidcircumvention of technological measures.

  5. Conveying Verbatim Copies.

    You may convey verbatim copies of the Program's source code as youreceive it, in any medium, provided that you conspicuously andappropriately publish on each copy an appropriate copyright notice;keep intact all notices stating that this License and anynon-permissive terms added in accord with section 7 apply to the code;keep intact all notices of the absence of any warranty; and give allrecipients a copy of this License along with the Program.

    You may charge any price or no price for each copy that you convey,and you may offer support or warranty protection for a fee.

  6. Conveying Modified Source Versions.

    You may convey a work based on the Program, or the modifications toproduce it from the Program, in the form of source code under theterms of section 4, provided that you also meet all of theseconditions:

    1. The work must carry prominent notices stating that you modified it,and giving a relevant date.
    2. The work must carry prominent notices stating that it is releasedunder this License and any conditions added under section 7. Thisrequirement modifies the requirement in section 4 to “keep intact allnotices”.
    3. You must license the entire work, as a whole, under this License toanyone who comes into possession of a copy. This License willtherefore apply, along with any applicable section 7 additional terms,to the whole of the work, and all its parts, regardless of how theyare packaged. This License gives no permission to license the work inany other way, but it does not invalidate such permission if you haveseparately received it.
    4. If the work has interactive user interfaces, each must displayAppropriate Legal Notices; however, if the Program has interactiveinterfaces that do not display Appropriate Legal Notices, your workneed not make them do so.

    A compilation of a covered work with other separate and independentworks, which are not by their nature extensions of the covered work,and which are not combined with it such as to form a larger program,in or on a volume of a storage or distribution medium, is called an“aggregate” if the compilation and its resulting copyright are notused to limit the access or legal rights of the compilation's usersbeyond what the individual works permit. Inclusion of a covered workin an aggregate does not cause this License to apply to the otherparts of the aggregate.

  7. Conveying Non-Source Forms.

    You may convey a covered work in object code form under the terms ofsections 4 and 5, provided that you also convey the machine-readableCorresponding Source under the terms of this License, in one of theseways:

    1. Convey the object code in, or embodied in, a physical product(including a physical distribution medium), accompanied by theCorresponding Source fixed on a durable physical medium customarilyused for software interchange.
    2. Convey the object code in, or embodied in, a physical product(including a physical distribution medium), accompanied by a writtenoffer, valid for at least three years and valid for as long as youoffer spare parts or customer support for that product model, to giveanyone who possesses the object code either (1) a copy of theCorresponding Source for all the software in the product that iscovered by this License, on a durable physical medium customarily usedfor software interchange, for a price no more than your reasonablecost of physically performing this conveying of source, or (2) accessto copy the Corresponding Source from a network server at no charge.
    3. Convey individual copies of the object code with a copy of the writtenoffer to provide the Corresponding Source. This alternative isallowed only occasionally and noncommercially, and only if youreceived the object code with such an offer, in accord with subsection6b.
    4. Convey the object code by offering access from a designated place(gratis or for a charge), and offer equivalent access to theCorresponding Source in the same way through the same place at nofurther charge. You need not require recipients to copy theCorresponding Source along with the object code. If the place to copythe object code is a network server, the Corresponding Source may beon a different server (operated by you or a third party) that supportsequivalent copying facilities, provided you maintain clear directionsnext to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remainobligated to ensure that it is available for as long as needed tosatisfy these requirements.
    5. Convey the object code using peer-to-peer transmission, provided youinform other peers where the object code and Corresponding Source ofthe work are being offered to the general public at no charge undersubsection 6d.

    A separable portion of the object code, whose source code is excludedfrom the Corresponding Source as a System Library, need not beincluded in conveying the object code work.

    A “User Product” is either (1) a “consumer product”, which means anytangible personal property which is normally used for personal,family, or household purposes, or (2) anything designed or sold forincorporation into a dwelling. In determining whether a product is aconsumer product, doubtful cases shall be resolved in favor ofcoverage. For a particular product received by a particular user,“normally used” refers to a typical or common use of that class ofproduct, regardless of the status of the particular user or of the wayin which the particular user actually uses, or expects or is expectedto use, the product. A product is a consumer product regardless ofwhether the product has substantial commercial, industrial ornon-consumer uses, unless such uses represent the only significantmode of use of the product.

    “Installation Information” for a User Product means any methods,procedures, authorization keys, or other information required toinstall and execute modified versions of a covered work in that UserProduct from a modified version of its Corresponding Source. Theinformation must suffice to ensure that the continued functioning ofthe modified object code is in no case prevented or interfered withsolely because modification has been made.

    If you convey an object code work under this section in, or with, orspecifically for use in, a User Product, and the conveying occurs aspart of a transaction in which the right of possession and use of theUser Product is transferred to the recipient in perpetuity or for afixed term (regardless of how the transaction is characterized), theCorresponding Source conveyed under this section must be accompaniedby the Installation Information. But this requirement does not applyif neither you nor any third party retains the ability to installmodified object code on the User Product (for example, the work hasbeen installed in ROM).

    The requirement to provide Installation Information does not include arequirement to continue to provide support service, warranty, orupdates for a work that has been modified or installed by therecipient, or for the User Product in which it has been modified orinstalled. Access to a network may be denied when the modificationitself materially and adversely affects the operation of the networkor violates the rules and protocols for communication across thenetwork.

    Corresponding Source conveyed, and Installation Information provided,in accord with this section must be in a format that is publiclydocumented (and with an implementation available to the public insource code form), and must require no special password or key forunpacking, reading or copying.

  8. Additional Terms.

    “Additional permissions” are terms that supplement the terms of thisLicense by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shallbe treated as though they were included in this License, to the extentthat they are valid under applicable law. If additional permissionsapply only to part of the Program, that part may be used separatelyunder those permissions, but the entire Program remains governed bythis License without regard to the additional permissions.

    When you convey a copy of a covered work, you may at your optionremove any additional permissions from that copy, or from any part ofit. (Additional permissions may be written to require their ownremoval in certain cases when you modify the work.) You may placeadditional permissions on material, added by you to a covered work,for which you have or can give appropriate copyright permission.

    Notwithstanding any other provision of this License, for material youadd to a covered work, you may (if authorized by the copyright holdersof that material) supplement the terms of this License with terms:

    1. Disclaiming warranty or limiting liability differently from the termsof sections 15 and 16 of this License; or
    2. Requiring preservation of specified reasonable legal notices or authorattributions in that material or in the Appropriate Legal Noticesdisplayed by works containing it; or
    3. Prohibiting misrepresentation of the origin of that material, orrequiring that modified versions of such material be marked inreasonable ways as different from the original version; or
    4. Limiting the use for publicity purposes of names of licensors orauthors of the material; or
    5. Declining to grant rights under trademark law for use of some tradenames, trademarks, or service marks; or
    6. Requiring indemnification of licensors and authors of that material byanyone who conveys the material (or modified versions of it) withcontractual assumptions of liability to the recipient, for anyliability that these contractual assumptions directly impose on thoselicensors and authors.

    All other non-permissive additional terms are considered “furtherrestrictions” within the meaning of section 10. If the Program as youreceived it, or any part of it, contains a notice stating that it isgoverned by this License along with a term that is a furtherrestriction, you may remove that term. If a license document containsa further restriction but permits relicensing or conveying under thisLicense, you may add to a covered work material governed by the termsof that license document, provided that the further restriction doesnot survive such relicensing or conveying.

    If you add terms to a covered work in accord with this section, youmust place, in the relevant source files, a statement of theadditional terms that apply to those files, or a notice indicatingwhere to find the applicable terms.

    Additional terms, permissive or non-permissive, may be stated in theform of a separately written license, or stated as exceptions; theabove requirements apply either way.

  9. Termination.

    You may not propagate or modify a covered work except as expresslyprovided under this License. Any attempt otherwise to propagate ormodify it is void, and will automatically terminate your rights underthis License (including any patent licenses granted under the thirdparagraph of section 11).

    However, if you cease all violation of this License, then your licensefrom a particular copyright holder is reinstated (a) provisionally,unless and until the copyright holder explicitly and finallyterminates your license, and (b) permanently, if the copyright holderfails to notify you of the violation by some reasonable means prior to60 days after the cessation.

    Moreover, your license from a particular copyright holder isreinstated permanently if the copyright holder notifies you of theviolation by some reasonable means, this is the first time you havereceived notice of violation of this License (for any work) from thatcopyright holder, and you cure the violation prior to 30 days afteryour receipt of the notice.

    Termination of your rights under this section does not terminate thelicenses of parties who have received copies or rights from you underthis License. If your rights have been terminated and not permanentlyreinstated, you do not qualify to receive new licenses for the samematerial under section 10.

  10. Acceptance Not Required for Having Copies.

    You are not required to accept this License in order to receive or runa copy of the Program. Ancillary propagation of a covered workoccurring solely as a consequence of using peer-to-peer transmissionto receive a copy likewise does not require acceptance. However,nothing other than this License grants you permission to propagate ormodify any covered work. These actions infringe copyright if you donot accept this License. Therefore, by modifying or propagating acovered work, you indicate your acceptance of this License to do so.

  11. Automatic Licensing of Downstream Recipients.

    Each time you convey a covered work, the recipient automaticallyreceives a license from the original licensors, to run, modify andpropagate that work, subject to this License. You are not responsiblefor enforcing compliance by third parties with this License.

    An “entity transaction” is a transaction transferring control of anorganization, or substantially all assets of one, or subdividing anorganization, or merging organizations. If propagation of a coveredwork results from an entity transaction, each party to thattransaction who receives a copy of the work also receives whateverlicenses to the work the party's predecessor in interest had or couldgive under the previous paragraph, plus a right to possession of theCorresponding Source of the work from the predecessor in interest, ifthe predecessor has it or can get it with reasonable efforts.

    You may not impose any further restrictions on the exercise of therights granted or affirmed under this License. For example, you maynot impose a license fee, royalty, or other charge for exercise ofrights granted under this License, and you may not initiate litigation(including a cross-claim or counterclaim in a lawsuit) alleging thatany patent claim is infringed by making, using, selling, offering forsale, or importing the Program or any portion of it.

  12. Patents.

    A “contributor” is a copyright holder who authorizes use under thisLicense of the Program or a work on which the Program is based. Thework thus licensed is called the contributor's “contributor version”.

    A contributor's “essential patent claims” are all patent claims ownedor controlled by the contributor, whether already acquired orhereafter acquired, that would be infringed by some manner, permittedby this License, of making, using, or selling its contributor version,but do not include claims that would be infringed only as aconsequence of further modification of the contributor version. Forpurposes of this definition, “control” includes the right to grantpatent sublicenses in a manner consistent with the requirements ofthis License.

    Each contributor grants you a non-exclusive, worldwide, royalty-freepatent license under the contributor's essential patent claims, tomake, use, sell, offer for sale, import and otherwise run, modify andpropagate the contents of its contributor version.

    In the following three paragraphs, a “patent license” is any expressagreement or commitment, however denominated, not to enforce a patent(such as an express permission to practice a patent or covenant not tosue for patent infringement). To “grant” such a patent license to aparty means to make such an agreement or commitment not to enforce apatent against the party.

    If you convey a covered work, knowingly relying on a patent license,and the Corresponding Source of the work is not available for anyoneto copy, free of charge and under the terms of this License, through apublicly available network server or other readily accessible means,then you must either (1) cause the Corresponding Source to be soavailable, or (2) arrange to deprive yourself of the benefit of thepatent license for this particular work, or (3) arrange, in a mannerconsistent with the requirements of this License, to extend the patentlicense to downstream recipients. “Knowingly relying” means you haveactual knowledge that, but for the patent license, your conveying thecovered work in a country, or your recipient's use of the covered workin a country, would infringe one or more identifiable patents in thatcountry that you have reason to believe are valid.

    If, pursuant to or in connection with a single transaction orarrangement, you convey, or propagate by procuring conveyance of, acovered work, and grant a patent license to some of the partiesreceiving the covered work authorizing them to use, propagate, modifyor convey a specific copy of the covered work, then the patent licenseyou grant is automatically extended to all recipients of the coveredwork and works based on it.

    A patent license is “discriminatory” if it does not include within thescope of its coverage, prohibits the exercise of, or is conditioned onthe non-exercise of one or more of the rights that are specificallygranted under this License. You may not convey a covered work if youare a party to an arrangement with a third party that is in thebusiness of distributing software, under which you make payment to thethird party based on the extent of your activity of conveying thework, and under which the third party grants, to any of the partieswho would receive the covered work from you, a discriminatory patentlicense (a) in connection with copies of the covered work conveyed byyou (or copies made from those copies), or (b) primarily for and inconnection with specific products or compilations that contain thecovered work, unless you entered into that arrangement, or that patentlicense was granted, prior to 28 March 2007.

    Nothing in this License shall be construed as excluding or limitingany implied license or other defenses to infringement that mayotherwise be available to you under applicable patent law.

  13. No Surrender of Others' Freedom.

    If conditions are imposed on you (whether by court order, agreement orotherwise) that contradict the conditions of this License, they do notexcuse you from the conditions of this License. If you cannot conveya covered work so as to satisfy simultaneously your obligations underthis License and any other pertinent obligations, then as aconsequence you may not convey it at all. For example, if you agreeto terms that obligate you to collect a royalty for further conveyingfrom those to whom you convey the Program, the only way you couldsatisfy both those terms and this License would be to refrain entirelyfrom conveying the Program.

  14. Use with the GNU Affero General Public License.

    Notwithstanding any other provision of this License, you havepermission to link or combine any covered work with a work licensedunder version 3 of the GNU Affero General Public License into a singlecombined work, and to convey the resulting work. The terms of thisLicense will continue to apply to the part which is the covered work,but the special requirements of the GNU Affero General Public License,section 13, concerning interaction through a network will apply to thecombination as such.

  15. Revised Versions of this License.

    The Free Software Foundation may publish revised and/or new versionsof the GNU General Public License from time to time. Such newversions will be similar in spirit to the present version, but maydiffer in detail to address new problems or concerns.

    Each version is given a distinguishing version number. If the Programspecifies that a certain numbered version of the GNU General PublicLicense “or any later version” applies to it, you have the option offollowing the terms and conditions either of that numbered version orof any later version published by the Free Software Foundation. Ifthe Program does not specify a version number of the GNU GeneralPublic License, you may choose any version ever published by the FreeSoftware Foundation.

    If the Program specifies that a proxy can decide which future versionsof the GNU General Public License can be used, that proxy's publicstatement of acceptance of a version permanently authorizes you tochoose that version for the Program.

    Later license versions may give you additional or differentpermissions. However, no additional obligations are imposed on anyauthor or copyright holder as a result of your choosing to follow alater version.

  16. Disclaimer of Warranty.

    THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BYAPPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHTHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS” WITHOUTWARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOTLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FORA PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY ANDPERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVEDEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR ORCORRECTION.

  17. Limitation of Liability.

    IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITINGWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/ORCONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGESARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUTNOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE ORLOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAMTO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHERPARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

  18. Interpretation of Sections 15 and 16.

    If the disclaimer of warranty and limitation of liability providedabove cannot be given local legal effect according to their terms,reviewing courts shall apply local law that most closely approximatesan absolute waiver of all civil liability in connection with theProgram, unless a warranty or assumption of liability accompanies acopy of the Program in return for a fee.

END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatestpossible use to the public, the best way to achieve this is to make itfree software which everyone can redistribute and change under theseterms.

To do so, attach the following notices to the program. It is safestto attach them to the start of each source file to most effectivelystate the exclusion of warranty; and each file should have at leastthe “copyright” line and a pointer to where the full notice is found.

     one line to give the program's name and a brief idea of what it does.
     Copyright (C) year name of author
     
     This program is free software: you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation, either version 3 of the License, or (at
     your option) any later version.
     
     This program is distributed in the hope that it will be useful, but
     WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     General Public License for more details.
     
     You should have received a copy of the GNU General Public License
     along with this program.  If not, see http://www.gnu.org/licenses/.

Also add information on how to contact you by electronic and paper mail.

If the program does terminal interaction, make it output a shortnotice like this when it starts in an interactive mode:

     program Copyright (C) year name of author
     This program comes with ABSOLUTELY NO WARRANTY; for details type ‘show w’.
     This is free software, and you are welcome to redistribute it
     under certain conditions; type ‘show c’ for details.

The hypothetical commands ‘show w’ and ‘show c’ should showthe appropriate parts of the General Public License. Of course, yourprogram's commands might be different; for a GUI interface, you woulduse an “about box”.

You should also get your employer (if you work as a programmer) or school,if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, seehttp://www.gnu.org/licenses/.

The GNU General Public License does not permit incorporating yourprogram into proprietary programs. If your program is a subroutinelibrary, you may consider it more useful to permit linking proprietaryapplications with the library. If this is what you want to do, usethe GNU Lesser General Public License instead of this License. Butfirst, please readhttp://www.gnu.org/philosophy/why-not-lgpl.html.


Next:  ,Previous:  Copying This Package,Up:  Top

Appendix B How to make copies of this manual

This appendix covers the license for copying this manual. Note thatsome of the longer examples in this manual are also distributed in thedirectorym4-1.4.16/examples/, where a morepermissive license is in effect when copying just the examples.

B.1 License for copying this manual

Version 1.3, 3 November 2008
     Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
     http://fsf.org/
     
     Everyone is permitted to copy and distribute verbatim copies
     of this license document, but changing it is not allowed.
  1. PREAMBLE

    The purpose of this License is to make a manual, textbook, or otherfunctional and useful documentfree in the sense of freedom: toassure everyone the effective freedom to copy and redistribute it,with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a wayto get credit for their work, while not being considered responsiblefor modifications made by others.

    This License is a kind of “copyleft”, which means that derivativeworks of the document must themselves be free in the same sense. Itcomplements the GNU General Public License, which is a copyleftlicense designed for free software.

    We have designed this License in order to use it for manuals for freesoftware, because free software needs free documentation: a freeprogram should come with manuals providing the same freedoms that thesoftware does. But this License is not limited to software manuals;it can be used for any textual work, regardless of subject matter orwhether it is published as a printed book. We recommend this Licenseprincipally for works whose purpose is instruction or reference.

  2. APPLICABILITY AND DEFINITIONS

    This License applies to any manual or other work, in any medium, thatcontains a notice placed by the copyright holder saying it can bedistributed under the terms of this License. Such a notice grants aworld-wide, royalty-free license, unlimited in duration, to use thatwork under the conditions stated herein. The “Document”, below,refers to any such manual or work. Any member of the public is alicensee, and is addressed as “you”. You accept the license if youcopy, modify or distribute the work in a way requiring permissionunder copyright law.

    A “Modified Version” of the Document means any work containing theDocument or a portion of it, either copied verbatim, or withmodifications and/or translated into another language.

    A “Secondary Section” is a named appendix or a front-matter sectionof the Document that deals exclusively with the relationship of thepublishers or authors of the Document to the Document's overallsubject (or to related matters) and contains nothing that could falldirectly within that overall subject. (Thus, if the Document is inpart a textbook of mathematics, a Secondary Section may not explainany mathematics.) The relationship could be a matter of historicalconnection with the subject or with related matters, or of legal,commercial, philosophical, ethical or political position regardingthem.

    The “Invariant Sections” are certain Secondary Sections whose titlesare designated, as being those of Invariant Sections, in the noticethat says that the Document is released under this License. If asection does not fit the above definition of Secondary then it is notallowed to be designated as Invariant. The Document may contain zeroInvariant Sections. If the Document does not identify any InvariantSections then there are none.

    The “Cover Texts” are certain short passages of text that are listed,as Front-Cover Texts or Back-Cover Texts, in the notice that says thatthe Document is released under this License. A Front-Cover Text maybe at most 5 words, and a Back-Cover Text may be at most 25 words.

    A “Transparent” copy of the Document means a machine-readable copy,represented in a format whose specification is available to thegeneral public, that is suitable for revising the documentstraightforwardly with generic text editors or (for images composed ofpixels) generic paint programs or (for drawings) some widely availabledrawing editor, and that is suitable for input to text formatters orfor automatic translation to a variety of formats suitable for inputto text formatters. A copy made in an otherwise Transparent fileformat whose markup, or absence of markup, has been arranged to thwartor discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amountof text. A copy that is not “Transparent” is called “Opaque”.

    Examples of suitable formats for Transparent copies include plainASCII without markup, Texinfo input format, LaTeX inputformat, SGML or XML using a publicly availableDTD, and standard-conforming simple HTML,PostScript or PDF designed for human modification. Examplesof transparent image formats include PNG, XCF andJPG. Opaque formats include proprietary formats that can beread and edited only by proprietary word processors, SGML orXML for which the DTD and/or processing tools arenot generally available, and the machine-generated HTML,PostScript or PDF produced by some word processors foroutput purposes only.

    The “Title Page” means, for a printed book, the title page itself,plus such following pages as are needed to hold, legibly, the materialthis License requires to appear in the title page. For works informats which do not have any title page as such, “Title Page” meansthe text near the most prominent appearance of the work's title,preceding the beginning of the body of the text.

    The “publisher” means any person or entity that distributes copiesof the Document to the public.

    A section “Entitled XYZ” means a named subunit of the Document whosetitle either is precisely XYZ or contains XYZ in parentheses followingtext that translates XYZ in another language. (Here XYZ stands for aspecific section name mentioned below, such as “Acknowledgements”,“Dedications”, “Endorsements”, or “History”.) To “Preserve the Title”of such a section when you modify the Document means that it remains asection “Entitled XYZ” according to this definition.

    The Document may include Warranty Disclaimers next to the notice whichstates that this License applies to the Document. These WarrantyDisclaimers are considered to be included by reference in thisLicense, but only as regards disclaiming warranties: any otherimplication that these Warranty Disclaimers may have is void and hasno effect on the meaning of this License.

  3. VERBATIM COPYING

    You may copy and distribute the Document in any medium, eithercommercially or noncommercially, provided that this License, thecopyright notices, and the license notice saying this License appliesto the Document are reproduced in all copies, and that you add no otherconditions whatsoever to those of this License. You may not usetechnical measures to obstruct or control the reading or furthercopying of the copies you make or distribute. However, you may acceptcompensation in exchange for copies. If you distribute a large enoughnumber of copies you must also follow the conditions in section 3.

    You may also lend copies, under the same conditions stated above, andyou may publicly display copies.

  4. COPYING IN QUANTITY

    If you publish printed copies (or copies in media that commonly haveprinted covers) of the Document, numbering more than 100, and theDocument's license notice requires Cover Texts, you must enclose thecopies in covers that carry, clearly and legibly, all these CoverTexts: Front-Cover Texts on the front cover, and Back-Cover Texts onthe back cover. Both covers must also clearly and legibly identifyyou as the publisher of these copies. The front cover must presentthe full title with all words of the title equally prominent andvisible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preservethe title of the Document and satisfy these conditions, can be treatedas verbatim copying in other respects.

    If the required texts for either cover are too voluminous to fitlegibly, you should put the first ones listed (as many as fitreasonably) on the actual cover, and continue the rest onto adjacentpages.

    If you publish or distribute Opaque copies of the Document numberingmore than 100, you must either include a machine-readable Transparentcopy along with each Opaque copy, or state in or with each Opaque copya computer-network location from which the general network-usingpublic has access to download using public-standard network protocolsa complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps,when you begin distribution of Opaque copies in quantity, to ensurethat this Transparent copy will remain thus accessible at the statedlocation until at least one year after the last time you distribute anOpaque copy (directly or through your agents or retailers) of thatedition to the public.

    It is requested, but not required, that you contact the authors of theDocument well before redistributing any large number of copies, to givethem a chance to provide you with an updated version of the Document.

  5. MODIFICATIONS

    You may copy and distribute a Modified Version of the Document underthe conditions of sections 2 and 3 above, provided that you releasethe Modified Version under precisely this License, with the ModifiedVersion filling the role of the Document, thus licensing distributionand modification of the Modified Version to whoever possesses a copyof it. In addition, you must do these things in the Modified Version:

    1. Use in the Title Page (and on the covers, if any) a title distinctfrom that of the Document, and from those of previous versions(which should, if there were any, be listed in the History sectionof the Document). You may use the same title as a previous versionif the original publisher of that version gives permission.
    2. List on the Title Page, as authors, one or more persons or entitiesresponsible for authorship of the modifications in the ModifiedVersion, together with at least five of the principal authors of theDocument (all of its principal authors, if it has fewer than five),unless they release you from this requirement.
    3. State on the Title page the name of the publisher of theModified Version, as the publisher.
    4. Preserve all the copyright notices of the Document.
    5. Add an appropriate copyright notice for your modificationsadjacent to the other copyright notices.
    6. Include, immediately after the copyright notices, a license noticegiving the public permission to use the Modified Version under theterms of this License, in the form shown in the Addendum below.
    7. Preserve in that license notice the full lists of Invariant Sectionsand required Cover Texts given in the Document's license notice.
    8. Include an unaltered copy of this License.
    9. Preserve the section Entitled “History”, Preserve its Title, and addto it an item stating at least the title, year, new authors, andpublisher of the Modified Version as given on the Title Page. Ifthere is no section Entitled “History” in the Document, create onestating the title, year, authors, and publisher of the Document asgiven on its Title Page, then add an item describing the ModifiedVersion as stated in the previous sentence.
    10. Preserve the network location, if any, given in the Document forpublic access to a Transparent copy of the Document, and likewisethe network locations given in the Document for previous versionsit was based on. These may be placed in the “History” section. You may omit a network location for a work that was published atleast four years before the Document itself, or if the originalpublisher of the version it refers to gives permission.
    11. For any section Entitled “Acknowledgements” or “Dedications”, Preservethe Title of the section, and preserve in the section all thesubstance and tone of each of the contributor acknowledgements and/ordedications given therein.
    12. Preserve all the Invariant Sections of the Document,unaltered in their text and in their titles. Section numbersor the equivalent are not considered part of the section titles.
    13. Delete any section Entitled “Endorsements”. Such a sectionmay not be included in the Modified Version.
    14. Do not retitle any existing section to be Entitled “Endorsements” orto conflict in title with any Invariant Section.
    15. Preserve any Warranty Disclaimers.

    If the Modified Version includes new front-matter sections orappendices that qualify as Secondary Sections and contain no materialcopied from the Document, you may at your option designate some or allof these sections as invariant. To do this, add their titles to thelist of Invariant Sections in the Modified Version's license notice. These titles must be distinct from any other section titles.

    You may add a section Entitled “Endorsements”, provided it containsnothing but endorsements of your Modified Version by variousparties—for example, statements of peer review or that the text hasbeen approved by an organization as the authoritative definition of astandard.

    You may add a passage of up to five words as a Front-Cover Text, and apassage of up to 25 words as a Back-Cover Text, to the end of the listof Cover Texts in the Modified Version. Only one passage ofFront-Cover Text and one of Back-Cover Text may be added by (orthrough arrangements made by) any one entity. If the Document alreadyincludes a cover text for the same cover, previously added by you orby arrangement made by the same entity you are acting on behalf of,you may not add another; but you may replace the old one, on explicitpermission from the previous publisher that added the old one.

    The author(s) and publisher(s) of the Document do not by this Licensegive permission to use their names for publicity for or to assert orimply endorsement of any Modified Version.

  6. COMBINING DOCUMENTS

    You may combine the Document with other documents released under thisLicense, under the terms defined in section 4 above for modifiedversions, provided that you include in the combination all of theInvariant Sections of all of the original documents, unmodified, andlist them all as Invariant Sections of your combined work in itslicense notice, and that you preserve all their Warranty Disclaimers.

    The combined work need only contain one copy of this License, andmultiple identical Invariant Sections may be replaced with a singlecopy. If there are multiple Invariant Sections with the same name butdifferent contents, make the title of each such section unique byadding at the end of it, in parentheses, the name of the originalauthor or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list ofInvariant Sections in the license notice of the combined work.

    In the combination, you must combine any sections Entitled “History”in the various original documents, forming one section Entitled“History”; likewise combine any sections Entitled “Acknowledgements”,and any sections Entitled “Dedications”. You must delete allsections Entitled “Endorsements.”

  7. COLLECTIONS OF DOCUMENTS

    You may make a collection consisting of the Document and other documentsreleased under this License, and replace the individual copies of thisLicense in the various documents with a single copy that is included inthe collection, provided that you follow the rules of this License forverbatim copying of each of the documents in all other respects.

    You may extract a single document from such a collection, and distributeit individually under this License, provided you insert a copy of thisLicense into the extracted document, and follow this License in allother respects regarding verbatim copying of that document.

  8. AGGREGATION WITH INDEPENDENT WORKS

    A compilation of the Document or its derivatives with other separateand independent documents or works, in or on a volume of a storage ordistribution medium, is called an “aggregate” if the copyrightresulting from the compilation is not used to limit the legal rightsof the compilation's users beyond what the individual works permit. When the Document is included in an aggregate, this License does notapply to the other works in the aggregate which are not themselvesderivative works of the Document.

    If the Cover Text requirement of section 3 is applicable to thesecopies of the Document, then if the Document is less than one half ofthe entire aggregate, the Document's Cover Texts may be placed oncovers that bracket the Document within the aggregate, or theelectronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the wholeaggregate.

  9. TRANSLATION

    Translation is considered a kind of modification, so you maydistribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires specialpermission from their copyright holders, but you may includetranslations of some or all Invariant Sections in addition to theoriginal versions of these Invariant Sections. You may include atranslation of this License, and all the license notices in theDocument, and any Warranty Disclaimers, provided that you also includethe original English version of this License and the original versionsof those notices and disclaimers. In case of a disagreement betweenthe translation and the original version of this License or a noticeor disclaimer, the original version will prevail.

    If a section in the Document is Entitled “Acknowledgements”,“Dedications”, or “History”, the requirement (section 4) to Preserveits Title (section 1) will typically require changing the actualtitle.

  10. TERMINATION

    You may not copy, modify, sublicense, or distribute the Documentexcept as expressly provided under this License. Any attemptotherwise to copy, modify, sublicense, or distribute it is void, andwill automatically terminate your rights under this License.

    However, if you cease all violation of this License, then your licensefrom a particular copyright holder is reinstated (a) provisionally,unless and until the copyright holder explicitly and finallyterminates your license, and (b) permanently, if the copyright holderfails to notify you of the violation by some reasonable means prior to60 days after the cessation.

    Moreover, your license from a particular copyright holder isreinstated permanently if the copyright holder notifies you of theviolation by some reasonable means, this is the first time you havereceived notice of violation of this License (for any work) from thatcopyright holder, and you cure the violation prior to 30 days afteryour receipt of the notice.

    Termination of your rights under this section does not terminate thelicenses of parties who have received copies or rights from you underthis License. If your rights have been terminated and not permanentlyreinstated, receipt of a copy of some or all of the same material doesnot give you any rights to use it.

  11. FUTURE REVISIONS OF THIS LICENSE

    The Free Software Foundation may publish new, revised versionsof the GNU Free Documentation License from time to time. Such newversions will be similar in spirit to the present version, but maydiffer in detail to address new problems or concerns. Seehttp://www.gnu.org/copyleft/.

    Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of thisLicense “or any later version” applies to it, you have the option offollowing the terms and conditions either of that specified version orof any later version that has been published (not as a draft) by theFree Software Foundation. If the Document does not specify a versionnumber of this License, you may choose any version ever published (notas a draft) by the Free Software Foundation. If the Documentspecifies that a proxy can decide which future versions of thisLicense can be used, that proxy's public statement of acceptance of aversion permanently authorizes you to choose that version for theDocument.

  12. RELICENSING

    “Massive Multiauthor Collaboration Site” (or “MMC Site”) means anyWorld Wide Web server that publishes copyrightable works and alsoprovides prominent facilities for anybody to edit those works. Apublic wiki that anybody can edit is an example of such a server. A“Massive Multiauthor Collaboration” (or “MMC”) contained in thesite means any set of copyrightable works thus published on the MMCsite.

    “CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0license published by Creative Commons Corporation, a not-for-profitcorporation with a principal place of business in San Francisco,California, as well as future copyleft versions of that licensepublished by that same organization.

    “Incorporate” means to publish or republish a Document, in whole orin part, as part of another Document.

    An MMC is “eligible for relicensing” if it is licensed under thisLicense, and if all works that were first published under this Licensesomewhere other than this MMC, and subsequently incorporated in wholeor in part into the MMC, (1) had no cover texts or invariant sections,and (2) were thus incorporated prior to November 1, 2008.

    The operator of an MMC Site may republish an MMC contained in the siteunder CC-BY-SA on the same site at any time before August 1, 2009,provided the MMC is eligible for relicensing.

ADDENDUM: How to use this License for your documents

To use this License in a document you have written, include a copy ofthe License in the document and put the following copyright andlicense notices just after the title page:

       Copyright (C)  year  your name.
       Permission is granted to copy, distribute and/or modify this document
       under the terms of the GNU Free Documentation License, Version 1.3
       or any later version published by the Free Software Foundation;
       with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
       Texts.  A copy of the license is included in the section entitled ``GNU
       Free Documentation License''.

If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts,replace the “with...Texts.” line with this:

         with the Invariant Sections being list their titles, with
         the Front-Cover Texts being list, and with the Back-Cover Texts
         being list.

If you have Invariant Sections without Cover Texts, or some othercombination of the three, merge those two alternatives to suit thesituation.

If your document contains nontrivial examples of program code, werecommend releasing these examples in parallel under your choice offree software license, such as the GNU General Public License,to permit their use in free software.


Previous:  Copying This Manual,Up:  Top

Appendix C Indices of concepts and macros


Next:  ,Up:  Indices

C.1 Index for all m4 macros

This index covers all m4 builtins, as well as several usefulcomposite macros. References are exclusively to the places where amacro is introduced the first time.


Previous:  Macro index,Up:  Indices

C.2 Index for many concepts

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值