7846 lines
302 KiB
Plaintext
7846 lines
302 KiB
Plaintext
This is m4.info, produced by makeinfo version 6.7 from m4.texi.
|
||
|
||
This manual (28 May 2021) is for GNU M4 (version 1.4.19), a package
|
||
containing an implementation of the m4 macro language.
|
||
|
||
Copyright © 1989–1994, 2004–2014, 2016–2017, 2020–2021 Free Software
|
||
Foundation, Inc.
|
||
|
||
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.”
|
||
INFO-DIR-SECTION Text creation and manipulation
|
||
START-INFO-DIR-ENTRY
|
||
* M4: (m4). A powerful macro processor.
|
||
END-INFO-DIR-ENTRY
|
||
|
||
|
||
File: m4.info, Node: Top, Next: Preliminaries, Up: (dir)
|
||
|
||
GNU M4
|
||
******
|
||
|
||
This manual (28 May 2021) is for GNU M4 (version 1.4.19), a package
|
||
containing an implementation of the m4 macro language.
|
||
|
||
Copyright © 1989–1994, 2004–2014, 2016–2017, 2020–2021 Free Software
|
||
Foundation, Inc.
|
||
|
||
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.”
|
||
|
||
GNU ‘m4’ is an implementation of the traditional UNIX macro
|
||
processor. It is mostly SVR4 compatible, although it has some
|
||
extensions (for example, handling more than 9 positional parameters to
|
||
macros). ‘m4’ also has builtin functions for including files, running
|
||
shell commands, doing arithmetic, etc. Autoconf needs GNU ‘m4’ for
|
||
generating ‘configure’ scripts, but not for running them.
|
||
|
||
GNU ‘m4’ was originally written by René Seindal, with subsequent
|
||
changes by François Pinard and other volunteers on the Internet. All
|
||
names and email addresses can be found in the files ‘m4-1.4.19/AUTHORS’
|
||
and ‘m4-1.4.19/THANKS’ from the GNU M4 distribution.
|
||
|
||
This is release 1.4.19. It is now considered stable: future releases
|
||
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 a “word” in ‘m4’. You should use:
|
||
./configure --enable-changeword
|
||
if you want this feature compiled in. The current implementation slows
|
||
down ‘m4’ considerably and is hardly acceptable. In the future, ‘m4’
|
||
2.0 will come with a different set of new features that provide similar
|
||
capabilities, but without the inefficiencies, so changeword will go away
|
||
and _you should not count on it_.
|
||
|
||
* Menu:
|
||
|
||
* Preliminaries:: Introduction and preliminaries
|
||
* Invoking m4:: Invoking ‘m4’
|
||
* Syntax:: Lexical and syntactic conventions
|
||
|
||
* Macros:: How to invoke macros
|
||
* Definitions:: How to define new macros
|
||
* Conditionals:: Conditionals, loops, and recursion
|
||
|
||
* Debugging:: How to debug macros and input
|
||
|
||
* Input Control:: Input control
|
||
* File Inclusion:: File inclusion
|
||
* Diversions:: Diverting and undiverting output
|
||
|
||
* Text handling:: Macros for text handling
|
||
* Arithmetic:: Macros for doing arithmetic
|
||
* Shell commands:: Macros for running shell commands
|
||
* Miscellaneous:: Miscellaneous builtin macros
|
||
* Frozen files:: Fast loading of frozen state
|
||
|
||
* Compatibility:: Compatibility with other versions of ‘m4’
|
||
* Answers:: Correct version of some examples
|
||
|
||
* Copying This Package:: How to make copies of the overall M4 package
|
||
* Copying This Manual:: How to make copies of this manual
|
||
* Indices:: Indices of concepts and macros
|
||
|
||
— The Detailed Node Listing —
|
||
|
||
Introduction and preliminaries
|
||
|
||
* Intro:: Introduction to ‘m4’
|
||
* History:: Historical references
|
||
* Bugs:: Problems and bugs
|
||
* Manual:: Using this manual
|
||
|
||
Invoking ‘m4’
|
||
|
||
* Operation modes:: Command line options for operation modes
|
||
* Preprocessor features:: Command line options for preprocessor features
|
||
* Limits control:: Command line options for limits control
|
||
* Frozen state:: Command line options for frozen state
|
||
* Debugging options:: Command line options for debugging
|
||
* Command line files:: Specifying input files on the command line
|
||
|
||
Lexical and syntactic conventions
|
||
|
||
* Names:: Macro names
|
||
* Quoted strings:: Quoting input to ‘m4’
|
||
* Comments:: Comments in ‘m4’ input
|
||
* Other tokens:: Other kinds of input tokens
|
||
* Input processing:: How ‘m4’ copies input to output
|
||
|
||
How to invoke macros
|
||
|
||
* Invocation:: Macro invocation
|
||
* Inhibiting Invocation:: Preventing macro invocation
|
||
* Macro Arguments:: Macro arguments
|
||
* Quoting Arguments:: On Quoting Arguments to macros
|
||
* Macro expansion:: Expanding macros
|
||
|
||
How to define new macros
|
||
|
||
* Define:: Defining a new macro
|
||
* Arguments:: Arguments to macros
|
||
* Pseudo Arguments:: Special arguments to macros
|
||
* Undefine:: Deleting a macro
|
||
* Defn:: Renaming macros
|
||
* Pushdef:: Temporarily redefining macros
|
||
|
||
* Indir:: Indirect call of macros
|
||
* Builtin:: Indirect call of builtins
|
||
|
||
Conditionals, loops, and recursion
|
||
|
||
* Ifdef:: Testing if a macro is defined
|
||
* Ifelse:: If-else construct, or multibranch
|
||
* Shift:: Recursion in ‘m4’
|
||
* Forloop:: Iteration by counting
|
||
* Foreach:: Iteration by list contents
|
||
* Stacks:: Working with definition stacks
|
||
* Composition:: Building macros with macros
|
||
|
||
How to debug macros and input
|
||
|
||
* Dumpdef:: Displaying macro definitions
|
||
* Trace:: Tracing macro calls
|
||
* Debug Levels:: Controlling debugging output
|
||
* Debug Output:: Saving debugging output
|
||
|
||
Input control
|
||
|
||
* Dnl:: Deleting whitespace in input
|
||
* Changequote:: Changing the quote characters
|
||
* Changecom:: Changing the comment delimiters
|
||
* Changeword:: Changing the lexical structure of words
|
||
* M4wrap:: Saving text until end of input
|
||
|
||
File inclusion
|
||
|
||
* Include:: Including named files
|
||
* Search Path:: Searching for include files
|
||
|
||
Diverting and undiverting output
|
||
|
||
* Divert:: Diverting output
|
||
* Undivert:: Undiverting output
|
||
* Divnum:: Diversion numbers
|
||
* Cleardivert:: Discarding diverted text
|
||
|
||
Macros for text handling
|
||
|
||
* Len:: Calculating length of strings
|
||
* Index macro:: Searching for substrings
|
||
* Regexp:: Searching for regular expressions
|
||
* Substr:: Extracting substrings
|
||
* Translit:: Translating characters
|
||
* Patsubst:: Substituting text by regular expression
|
||
* Format:: Formatting strings (printf-like)
|
||
|
||
Macros for doing arithmetic
|
||
|
||
* Incr:: Decrement and increment operators
|
||
* Eval:: Evaluating integer expressions
|
||
|
||
Macros for running shell commands
|
||
|
||
* Platform macros:: Determining the platform
|
||
* Syscmd:: Executing simple commands
|
||
* Esyscmd:: Reading the output of commands
|
||
* Sysval:: Exit status
|
||
* Mkstemp:: Making temporary files
|
||
|
||
Miscellaneous builtin macros
|
||
|
||
* Errprint:: Printing error messages
|
||
* Location:: Printing current location
|
||
* M4exit:: Exiting from ‘m4’
|
||
|
||
Fast loading of frozen state
|
||
|
||
* Using frozen files:: Using frozen files
|
||
* Frozen file format:: Frozen file format
|
||
|
||
Compatibility with other versions of ‘m4’
|
||
|
||
* Extensions:: Extensions in GNU M4
|
||
* Incompatibilities:: Facilities in System V m4 not in GNU M4
|
||
* Other Incompatibilities:: Other incompatibilities
|
||
|
||
Correct version of some examples
|
||
|
||
* Improved exch:: Solution for ‘exch’
|
||
* Improved forloop:: Solution for ‘forloop’
|
||
* Improved foreach:: Solution for ‘foreach’
|
||
* Improved copy:: Solution for ‘copy’
|
||
* Improved m4wrap:: Solution for ‘m4wrap’
|
||
* Improved cleardivert:: Solution for ‘cleardivert’
|
||
* Improved capitalize:: Solution for ‘capitalize’
|
||
* Improved fatal_error:: Solution for ‘fatal_error’
|
||
|
||
How to make copies of the overall M4 package
|
||
|
||
* GNU General Public License:: License for copying the M4 package
|
||
|
||
How to make copies of this manual
|
||
|
||
* GNU Free Documentation License:: License for copying this manual
|
||
|
||
Indices of concepts and macros
|
||
|
||
* Macro index:: Index for all ‘m4’ macros
|
||
* Concept index:: Index for many concepts
|
||
|
||
|
||
|
||
File: m4.info, Node: Preliminaries, Next: Invoking m4, Prev: Top, Up: Top
|
||
|
||
1 Introduction and preliminaries
|
||
********************************
|
||
|
||
This first chapter explains what GNU ‘m4’ is, where ‘m4’ comes from, how
|
||
to read and use this documentation, how to call the ‘m4’ program, and
|
||
how to report bugs about it. It concludes by giving tips for reading
|
||
the remainder of the manual.
|
||
|
||
The following chapters then detail all the features of the ‘m4’
|
||
language.
|
||
|
||
* Menu:
|
||
|
||
* Intro:: Introduction to ‘m4’
|
||
* History:: Historical references
|
||
* Bugs:: Problems and bugs
|
||
* Manual:: Using this manual
|
||
|
||
|
||
File: m4.info, Node: Intro, Next: History, Up: Preliminaries
|
||
|
||
1.1 Introduction to ‘m4’
|
||
========================
|
||
|
||
‘m4’ is a macro processor, in the sense that it copies its input to the
|
||
output, expanding macros as it goes. Macros are either builtin or
|
||
user-defined, and can take any number of arguments. Besides just doing
|
||
macro expansion, ‘m4’ has builtin functions for including named files,
|
||
running shell commands, doing integer arithmetic, 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 has
|
||
been standardized by POSIX. Usually, only a small percentage of users
|
||
are aware of its existence. However, those who find it often become
|
||
committed users. The popularity of GNU Autoconf, which requires GNU
|
||
‘m4’ for _generating_ ‘configure’ scripts, is an incentive for many to
|
||
install it, while these people will not themselves program in ‘m4’. GNU
|
||
‘m4’ is mostly compatible with the System V, Release 4 version, except
|
||
for some minor differences. *Note Compatibility::, for more details.
|
||
|
||
Some people find ‘m4’ to be fairly addictive. They first use ‘m4’
|
||
for simple problems, then take bigger and bigger challenges, learning
|
||
how to write complex sets of ‘m4’ macros along the way. Once really
|
||
addicted, users pursue writing of sophisticated ‘m4’ applications even
|
||
to solve simple problems, devoting more time debugging their ‘m4’
|
||
scripts than doing real work. Beware that ‘m4’ may be dangerous for the
|
||
health of compulsive programmers.
|
||
|
||
|
||
File: m4.info, Node: History, Next: Bugs, Prev: Intro, Up: Preliminaries
|
||
|
||
1.2 Historical references
|
||
=========================
|
||
|
||
Macro languages were invented early in the history of computing. In the
|
||
1950s Alan Perlis suggested that the macro language be independent of
|
||
the language being processed. Techniques such as conditional and
|
||
recursive macros, and using macros to define other macros, were
|
||
described by Doug McIlroy of Bell Labs in “Macro Instruction Extensions
|
||
of Compiler Languages”, _Communications of the ACM_ 3, 4 (1960), 214–20,
|
||
<https://dl.acm.org/doi/10.1145/367177.367223>.
|
||
|
||
An important precursor of ‘m4’ was GPM; see C. Strachey, “A general
|
||
purpose macrogenerator”, _Computer Journal_ 8, 3 (1965), 225–41,
|
||
<https://academic.oup.com/comjnl/article/8/3/225/336044>. GPM is also
|
||
succinctly described in David Gries’s book _Compiler Construction for
|
||
Digital Computers_, Wiley (1971). Strachey was a brilliant programmer:
|
||
GPM fit into 250 machine instructions!
|
||
|
||
Inspired by GPM while visiting Strachey’s Lab in 1968, McIlroy wrote
|
||
a model preprocessor in that fit into a page of Snobol 3 code, and
|
||
McIlroy and Robert Morris developed a series of further models at Bell
|
||
Labs. Andrew D. Hall followed up with M6, a general purpose macro
|
||
processor used to port the Fortran source code of the Altran computer
|
||
algebra system; see Hall’s “The M6 Macro Processor”, Computing Science
|
||
Technical Report #2, Bell Labs (1972),
|
||
<http://cm.bell-labs.com/cm/cs/cstr/2.pdf>. M6’s source code consisted
|
||
of about 600 Fortran statements. Its name was the first of the ‘m4’
|
||
line.
|
||
|
||
The Brian Kernighan and P.J. Plauger book _Software Tools_,
|
||
Addison-Wesley (1976), describes and implements a Unix macro-processor
|
||
language, which inspired Dennis Ritchie to write ‘m3’, a macro processor
|
||
for the AP-3 minicomputer.
|
||
|
||
Kernighan and Ritchie then joined forces to develop the original
|
||
‘m4’, described in “The M4 Macro Processor”, Bell Laboratories (1977),
|
||
<https://wolfram.schneider.org/bsd/7thEdManVol2/m4/m4.pdf>. It had only
|
||
21 builtin macros.
|
||
|
||
While ‘GPM’ was more _pure_, ‘m4’ is meant to deal with the true
|
||
intricacies of real life: macros can be recognized without being
|
||
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 then ‘m3’,
|
||
formed the engine for the Rational FORTRAN preprocessor, that is, the
|
||
‘Ratfor’ equivalent of ‘cpp’. Later, ‘m4’ was used as a front-end for
|
||
‘Ratfor’, ‘C’ and ‘Cobol’.
|
||
|
||
René Seindal released his implementation of ‘m4’, GNU ‘m4’, in 1990,
|
||
with the aim of removing the artificial limitations in many of the
|
||
traditional ‘m4’ implementations, such as maximum line length, macro
|
||
size, or number of macros.
|
||
|
||
The late Professor A. Dain Samples described and implemented a
|
||
further evolution in the form of ‘M5’: “User’s Guide to the M5 Macro
|
||
Language: 2nd edition”, Electronic Announcement on comp.compilers
|
||
newsgroup (1992).
|
||
|
||
François Pinard took over maintenance of GNU ‘m4’ in 1992, until 1994
|
||
when he released GNU ‘m4’ 1.4, which was the stable release for 10
|
||
years. It was at this time that GNU Autoconf decided to require GNU
|
||
‘m4’ as its underlying engine, since all other implementations of ‘m4’
|
||
had too many limitations.
|
||
|
||
More recently, in 2004, Paul Eggert released 1.4.1 and 1.4.2 which
|
||
addressed some long standing bugs in the venerable 1.4 release. Then in
|
||
2005, Gary V. Vaughan collected together the many patches to GNU ‘m4’
|
||
1.4 that were floating around the net and released 1.4.3 and 1.4.4. And
|
||
in 2006, Eric Blake joined the team and prepared patches for the release
|
||
of 1.4.5, with subsequent releases through intervening years, as recent
|
||
as 1.4.18 in 2016.
|
||
|
||
Meanwhile, development has continued on new features for ‘m4’, such
|
||
as dynamic module loading and additional builtins. When complete, GNU
|
||
‘m4’ 2.0 will start a new series of releases.
|
||
|
||
|
||
File: m4.info, Node: Bugs, Next: Manual, Prev: 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 actually found a
|
||
real bug. Carefully reread the documentation and see if it really says
|
||
you can do what you’re trying to do. If it’s not clear whether you
|
||
should be able to do something or not, report that too; it’s a bug in
|
||
the documentation!
|
||
|
||
Before reporting a bug or trying to fix it yourself, try to isolate
|
||
it to the smallest possible input file that reproduces the problem.
|
||
Then send us the input file and the exact results ‘m4’ gave you. Also
|
||
say what you expected to occur; this will help us decide whether the
|
||
problem was really in the documentation.
|
||
|
||
Once you’ve got a precise problem, send e-mail to <bug-m4@gnu.org>.
|
||
Please include the version number of ‘m4’ you are using. You can get
|
||
this information with the command ‘m4 --version’. Also provide details
|
||
about the platform you are executing on.
|
||
|
||
Non-bug suggestions are always welcome as well. If you have
|
||
questions about things that are unclear in the documentation or are just
|
||
obscure features, please report them too.
|
||
|
||
|
||
File: m4.info, Node: Manual, Prev: Bugs, Up: Preliminaries
|
||
|
||
1.4 Using this manual
|
||
=====================
|
||
|
||
This manual contains a number of examples of ‘m4’ input and output, and
|
||
a simple notation is used to distinguish input, output and error
|
||
messages from ‘m4’. Examples are set out from the normal text, and
|
||
shown in a fixed width font, like this
|
||
|
||
This is an example of an example!
|
||
|
||
To distinguish input from output, all output from ‘m4’ is prefixed by
|
||
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 input file.
|
||
The sequence ‘<NL>’ refers to the newline character. The majority of
|
||
these examples are self-contained, and you can run them with similar
|
||
results by invoking ‘m4 -d’. In fact, the testsuite that is bundled in
|
||
the GNU M4 package consists of the examples in this document! Some of
|
||
the examples assume that your current directory is located where you
|
||
unpacked the installation, so if you plan on following along, you may
|
||
find it helpful to do this now:
|
||
|
||
$ cd m4-1.4.19
|
||
|
||
As each of the predefined macros in ‘m4’ is described, a prototype
|
||
call of the macro will be shown, giving descriptive names to the
|
||
arguments, e.g.,
|
||
|
||
-- Composite: example (STRING, [COUNT = ‘1’], [ARGUMENT]...)
|
||
This is a sample prototype. There is not really a macro named
|
||
‘example’, but this documents that if there were, it would be a
|
||
Composite macro, rather than a Builtin. It requires at least one
|
||
argument, STRING. Remember that in ‘m4’, there must not be a space
|
||
between the macro name and the opening parenthesis, unless it was
|
||
intended to call the macro without any arguments. The brackets
|
||
around COUNT and ARGUMENT show that these arguments are optional.
|
||
If COUNT is omitted, the macro behaves as if count were ‘1’,
|
||
whereas if ARGUMENT is omitted, the macro behaves as if it were the
|
||
empty string. A blank argument is not the same as an omitted
|
||
argument. For example, ‘example(`a')’, ‘example(`a',`1')’, and
|
||
‘example(`a',`1',)’ would behave identically with COUNT set to ‘1’;
|
||
while ‘example(`a',)’ and ‘example(`a',`')’ would explicitly pass
|
||
the empty string for COUNT. The ellipses (‘...’) show that the
|
||
macro processes additional arguments after ARGUMENT, rather than
|
||
ignoring them.
|
||
|
||
All macro arguments in ‘m4’ are strings, but some are given special
|
||
interpretation, e.g., as numbers, file names, regular expressions, etc.
|
||
The documentation for each macro will state how the parameters are
|
||
interpreted, and what happens if the argument cannot be parsed according
|
||
to the desired interpretation. Unless specified otherwise, a parameter
|
||
specified to be a number is parsed as a decimal, even if the argument
|
||
has leading zeros; and parsing the empty string as a number results in 0
|
||
rather than an error, although a warning will be issued.
|
||
|
||
This document consistently writes and uses “builtin”, without a
|
||
hyphen, as if it were an English word. This is how the ‘builtin’
|
||
primitive is spelled within ‘m4’.
|
||
|
||
|
||
File: m4.info, Node: Invoking m4, Next: Syntax, Prev: Preliminaries, Up: Top
|
||
|
||
2 Invoking ‘m4’
|
||
***************
|
||
|
||
The format of the ‘m4’ 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, any
|
||
unambiguous prefix is sufficient. POSIX requires ‘m4’ to recognize
|
||
arguments intermixed with files, even when ‘POSIXLY_CORRECT’ is set in
|
||
the environment. Most options take effect at startup regardless of
|
||
their position, but some are documented below as taking effect after any
|
||
files that occurred earlier in the command line. The argument ‘--’ is a
|
||
marker to denote the end of options.
|
||
|
||
With short options, options that do not take arguments may be
|
||
combined into a single command line argument with subsequent options,
|
||
options with mandatory arguments may be provided either as a single
|
||
command line argument or as two arguments, and options with optional
|
||
arguments must be provided as a single argument. In other words, ‘m4
|
||
-QPDfoo -d a -df’ is equivalent to ‘m4 -Q -P -D foo -d -df -- ./a’,
|
||
although the latter form is considered canonical.
|
||
|
||
With long options, options with mandatory arguments may be provided
|
||
with an equal sign (‘=’) in a single argument, or as two arguments, and
|
||
options with optional arguments must be provided as a single argument.
|
||
In other words, ‘m4 --def foo --debug a’ is equivalent to ‘m4
|
||
--define=foo --debug= -- ./a’, although the latter form is considered
|
||
canonical (not to mention more robust, in case a future version of ‘m4’
|
||
introduces an option named ‘--default’).
|
||
|
||
‘m4’ understands the following options, grouped by functionality.
|
||
|
||
* Menu:
|
||
|
||
* Operation modes:: Command line options for operation modes
|
||
* Preprocessor features:: Command line options for preprocessor features
|
||
* Limits control:: Command line options for limits control
|
||
* Frozen state:: Command line options for frozen state
|
||
* Debugging options:: Command line options for debugging
|
||
* Command line files:: Specifying input files on the command line
|
||
|
||
|
||
File: m4.info, Node: Operation modes, Next: Preprocessor features, Up: Invoking m4
|
||
|
||
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 other actions.
|
||
|
||
‘--version’
|
||
Print the version number of the program on standard output, then
|
||
immediately exit ‘m4’ without reading any input files or performing
|
||
any other actions.
|
||
|
||
‘-E’
|
||
‘--fatal-warnings’
|
||
Controls the effect of warnings. If unspecified, then execution
|
||
continues and exit status is unaffected when a warning is printed.
|
||
If specified exactly once, warnings become fatal; when one is
|
||
issued, execution continues, but the exit status will be non-zero.
|
||
If specified multiple times, then execution halts with non-zero
|
||
status the first time a warning is issued. The introduction of
|
||
behavior levels is new to M4 1.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 all
|
||
output will be unbuffered, and interrupts will be ignored. The
|
||
spelling ‘-e’ exists for compatibility with other ‘m4’
|
||
implementations, and issues a warning because it may be withdrawn
|
||
in a future version of GNU M4.
|
||
|
||
‘-P’
|
||
‘--prefix-builtins’
|
||
Internally modify _all_ builtin macro names so they all start with
|
||
the 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 ‘-R’ is also specified.
|
||
|
||
‘-Q’
|
||
‘--quiet’
|
||
‘--silent’
|
||
Suppress warnings, such as missing or superfluous arguments in
|
||
macro calls, or treating the empty string as zero.
|
||
|
||
‘--warn-macro-sequence[=REGEXP]’
|
||
Issue a warning if the regular expression REGEXP has a non-empty
|
||
match in any macro definition (either by ‘define’ or ‘pushdef’).
|
||
Empty matches are ignored; therefore, supplying the empty 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 by multiple
|
||
digits or by an open brace), since these sequences will change
|
||
semantics in the default operation of GNU M4 2.0 (due to a change
|
||
in how more than 9 arguments in a macro definition will be handled,
|
||
*note Arguments::). Providing an alternate regular expression can
|
||
provide a useful reverse lookup feature of finding where a macro is
|
||
defined to have a given definition.
|
||
|
||
‘-W REGEXP’
|
||
‘--word-regexp=REGEXP’
|
||
Use REGEXP as an alternative syntax for macro names. This
|
||
experimental option will not be present in all GNU ‘m4’
|
||
implementations (*note Changeword::).
|
||
|
||
|
||
File: m4.info, Node: Preprocessor features, Next: Limits control, Prev: Operation modes, Up: Invoking m4
|
||
|
||
2.2 Command line options for preprocessor features
|
||
==================================================
|
||
|
||
Several options allow ‘m4’ to behave more like a preprocessor. Macro
|
||
definitions and deletions can be made on the command line, the search
|
||
path can be altered, and the output file can track where the input came
|
||
from. These features occur with the following options:
|
||
|
||
‘-D NAME[=VALUE]’
|
||
‘--define=NAME[=VALUE]’
|
||
This enters NAME into the symbol table. If ‘=VALUE’ is missing,
|
||
the value is taken to be the empty string. The VALUE can be any
|
||
string, and the macro can be defined to take arguments, just as if
|
||
it was defined from within the input. This option may be given
|
||
more than once; order with respect to file names is significant,
|
||
and redefining the same NAME loses the previous value.
|
||
|
||
‘-I DIRECTORY’
|
||
‘--include=DIRECTORY’
|
||
Make ‘m4’ search DIRECTORY for included files that are not found in
|
||
the current working directory. *Note Search Path::, for more
|
||
details. This option may be given more than once.
|
||
|
||
‘-s’
|
||
‘--synclines’
|
||
Generate synchronization lines, for use by the C preprocessor or
|
||
other similar tools. Order is significant with respect to file
|
||
names. This option is useful, for example, when ‘m4’ is used as a
|
||
front end to a compiler. Source file name and line number
|
||
information is conveyed by directives of the form ‘#line LINENUM
|
||
"FILE"’, which are inserted as needed into the middle of the
|
||
output. Such directives mean that the following line originated or
|
||
was expanded from the contents of input file FILE at line LINENUM.
|
||
The ‘"FILE"’ part is often omitted when the file name did not
|
||
change from the previous directive.
|
||
|
||
Synchronization directives are always given on complete lines by
|
||
themselves. When a synchronization discrepancy occurs in the
|
||
middle of an output line, the associated synchronization directive
|
||
is delayed until the next newline that does not occur in the middle
|
||
of a quoted string 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
|
||
be given more than once; undefining a NAME that does not have a
|
||
definition is silently ignored. Order is significant with respect
|
||
to file names.
|
||
|
||
|
||
File: m4.info, Node: Limits control, Next: Frozen state, Prev: Preprocessor features, Up: Invoking m4
|
||
|
||
2.3 Command line options for limits control
|
||
===========================================
|
||
|
||
There are some limits within ‘m4’ that can be tuned. For compatibility,
|
||
‘m4’ also accepts some options that control limits in other
|
||
implementations, but which are automatically unbounded (limited only by
|
||
your hardware and operating system constraints) in GNU ‘m4’.
|
||
|
||
‘-g’
|
||
‘--gnu’
|
||
Enable all the extensions in this implementation. In this release
|
||
of M4, this option is always on by default; it is currently only
|
||
useful when overriding a prior use of ‘--traditional’. However,
|
||
having GNU behavior as default makes it impossible to write a
|
||
strictly POSIX-compliant client that avoids all incompatible GNU M4
|
||
extensions, since such a client would have to use the non-POSIX
|
||
command-line option to force full POSIX behavior. Thus, a future
|
||
version of M4 will be changed to implicitly use the option
|
||
‘--traditional’ if the environment variable ‘POSIXLY_CORRECT’ is
|
||
set. Projects that intentionally use GNU extensions should
|
||
consider using ‘--gnu’ to state their intentions, so that the
|
||
project will not mysteriously break if the user upgrades to a newer
|
||
M4 and has ‘POSIXLY_CORRECT’ set in their environment.
|
||
|
||
‘-G’
|
||
‘--traditional’
|
||
Suppress all the extensions made in this implementation, compared
|
||
to the System V version. *Note 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 not
|
||
checked. The default is 65537 entries. It should not be necessary
|
||
to increase 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
|
||
not specified, nesting defaults to unlimited on platforms that can
|
||
detect stack overflow, and to 1024 levels otherwise. A value of
|
||
zero means unlimited; but then heavily nested code could
|
||
potentially cause a stack overflow.
|
||
|
||
The precise effect of this option is more correctly associated with
|
||
textual nesting than dynamic recursion. It has been useful when
|
||
some complex ‘m4’ input was generated by mechanical means, and also
|
||
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 endless rescanning
|
||
loops, since these do not necessarily consume much memory or stack
|
||
space. Through clever usage of rescanning loops, one can request
|
||
complex, time-consuming computations from ‘m4’ with useful results.
|
||
Putting limitations in this area would break ‘m4’ power. There are
|
||
many pathological cases: ‘define(`a', `a')a’ is only the simplest
|
||
example (but *note Compatibility::). Expecting GNU ‘m4’ to detect
|
||
these would be a little like expecting a compiler system to detect
|
||
and diagnose endless loops: it is a quite _hard_ problem in
|
||
general, if not undecidable!
|
||
|
||
‘-B NUM’
|
||
‘-S NUM’
|
||
‘-T NUM’
|
||
These options are present for compatibility with System V ‘m4’, but
|
||
do nothing in this implementation. They may disappear in future
|
||
releases, and issue a warning to that effect.
|
||
|
||
‘-N NUM’
|
||
‘--diversions=NUM’
|
||
These options are present only for compatibility with previous
|
||
versions of GNU ‘m4’, and were controlling the number of possible
|
||
diversions which could be used at the same time. They do nothing,
|
||
because there is no fixed limit anymore. They may disappear in
|
||
future releases, and issue a warning to that effect.
|
||
|
||
|
||
File: m4.info, Node: Frozen state, Next: Debugging options, Prev: Limits control, Up: Invoking m4
|
||
|
||
2.4 Command line options for frozen state
|
||
=========================================
|
||
|
||
GNU ‘m4’ comes with a feature of freezing internal state (*note Frozen
|
||
files::). This can be used to speed up ‘m4’ execution 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
|
||
end in ‘.m4f’.
|
||
|
||
‘-R FILE’
|
||
‘--reload-state=FILE’
|
||
Before execution starts, recover the internal state from the
|
||
specified frozen FILE. The options ‘-D’, ‘-U’, and ‘-t’ take
|
||
effect after state is reloaded, but before the input files are
|
||
read.
|
||
|
||
|
||
File: m4.info, Node: Debugging options, Next: Command line files, Prev: Frozen state, Up: Invoking m4
|
||
|
||
2.5 Command line options for debugging
|
||
======================================
|
||
|
||
Finally, there are several options for aiding in debugging ‘m4’ scripts.
|
||
|
||
‘-d[FLAGS]’
|
||
‘--debug[=FLAGS]’
|
||
Set the debug-level according to the flags FLAGS. The debug-level
|
||
controls the format and amount of information presented by the
|
||
debugging functions. *Note Debug Levels::, for more details on the
|
||
format and meaning of FLAGS. If omitted, FLAGS defaults to ‘aeq’.
|
||
|
||
‘--debugfile[=FILE]’
|
||
‘-o FILE’
|
||
‘--error-output=FILE’
|
||
Redirect ‘dumpdef’ output, debug messages, and trace output to the
|
||
named FILE. Warnings, error messages, and ‘errprint’ output are
|
||
still printed to standard error. If these options are not used, or
|
||
if FILE is unspecified (only possible for ‘--debugfile’), debug
|
||
output goes to standard error; if FILE is the empty string, debug
|
||
output is discarded. *Note Debug Output::, for more details. The
|
||
option ‘--debugfile’ may be given more than once, and order is
|
||
significant with respect to file names. The spellings ‘-o’ and
|
||
‘--error-output’ are misleading and inconsistent with other GNU
|
||
tools; for now they are silently accepted as synonyms of
|
||
‘--debugfile’ and only recognized once, but in a future version of
|
||
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 NUM
|
||
characters per trace line. If unspecified or zero, output is
|
||
unlimited. *Note Debug Levels::, for more details.
|
||
|
||
‘-t NAME’
|
||
‘--trace=NAME’
|
||
This enables tracing for the macro NAME, at any point where it is
|
||
defined. NAME need not be defined when this option is given. This
|
||
option may be given more than once, and order is significant with
|
||
respect to file names. *Note Trace::, for more details.
|
||
|
||
|
||
File: m4.info, Node: Command line files, Prev: 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 file
|
||
names. If no names are present, standard input is read. A file name of
|
||
‘-’ is taken to mean standard input. It is conventional, but not
|
||
required, for input files to end in ‘.m4’.
|
||
|
||
The input files are read in the sequence given. Standard input can
|
||
be read more than once, so the file name ‘-’ may appear multiple times
|
||
on the command line; this makes a difference when input is from a
|
||
terminal or other special file type. It is an error if an input file
|
||
ends in the middle of argument collection, a comment, or a quoted
|
||
string.
|
||
|
||
The options ‘--define’ (‘-D’), ‘--undefine’ (‘-U’), ‘--synclines’
|
||
(‘-s’), and ‘--trace’ (‘-t’) only take effect after processing input
|
||
from any file names that occur earlier on the command line. For
|
||
example, assume the file ‘foo’ contains:
|
||
|
||
$ cat foo
|
||
bar
|
||
|
||
The text ‘bar’ can then be redefined over multiple uses of ‘foo’:
|
||
|
||
$ m4 -Dbar=hello foo -Dbar=world foo
|
||
⇒hello
|
||
⇒world
|
||
|
||
If none of the input files invoked ‘m4exit’ (*note M4exit::), the
|
||
exit status of ‘m4’ will be 0 for success, 1 for general failure (such
|
||
as problems with reading an input file), and 63 for version mismatch
|
||
(*note Using frozen files::).
|
||
|
||
If you need to read a file whose name starts with a ‘-’, you can
|
||
specify it as ‘./-file’, or use ‘--’ to mark the end of options.
|
||
|
||
|
||
File: m4.info, Node: Syntax, Next: Macros, Prev: Invoking m4, Up: Top
|
||
|
||
3 Lexical and syntactic conventions
|
||
***********************************
|
||
|
||
As ‘m4’ reads its input, it separates it into “tokens”. A token is
|
||
either a name, a quoted string, or any single character, that is not a
|
||
part of either a name or a string. Input to ‘m4’ can also contain
|
||
comments. GNU ‘m4’ does not yet understand multibyte locales; all
|
||
operations are byte-oriented rather than character-oriented (although if
|
||
your locale uses a single byte encoding, such as ISO-8859-1, you will
|
||
not notice a difference). However, ‘m4’ is eight-bit clean, so you can
|
||
use non-ASCII characters in quoted strings (*note Changequote::),
|
||
comments (*note Changecom::), and macro names (*note Indir::), with the
|
||
exception of the NUL character (the zero byte ‘'\0'’).
|
||
|
||
* Menu:
|
||
|
||
* Names:: Macro names
|
||
* Quoted strings:: Quoting input to ‘m4’
|
||
* Comments:: Comments in ‘m4’ input
|
||
* Other tokens:: Other kinds of input tokens
|
||
* Input processing:: How ‘m4’ copies input to output
|
||
|
||
|
||
File: m4.info, Node: Names, Next: Quoted strings, 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’ will use
|
||
the longest such sequence found in the input. If a name has a macro
|
||
definition, it will be subject to macro expansion (*note Macros::).
|
||
Names are case-sensitive.
|
||
|
||
Examples of legal names are: ‘foo’, ‘_tmp’, and ‘name01’.
|
||
|
||
|
||
File: m4.info, Node: Quoted strings, Next: Comments, Prev: Names, Up: Syntax
|
||
|
||
3.2 Quoting input to ‘m4’
|
||
=========================
|
||
|
||
A quoted string is a sequence of characters surrounded by quote strings,
|
||
defaulting to ‘`’ and ‘'’, where the nested begin and end quotes within
|
||
the string are balanced. The value of a string token is the text, with
|
||
one level 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
|
||
macro ‘changequote’. *Note Changequote::, for more information.
|
||
|
||
|
||
File: m4.info, Node: Comments, Next: Other tokens, Prev: 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 to the
|
||
output—comments are _not_ discarded by ‘m4’.
|
||
|
||
Comments cannot be nested, so the first newline after a ‘#’ ends the
|
||
comment. The commenting effect of the begin-comment string can 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,
|
||
using the builtin macro ‘changecom’. *Note Changecom::, for more
|
||
information.
|
||
|
||
|
||
File: m4.info, Node: Other tokens, Next: Input processing, Prev: 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 macro
|
||
expansion, 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 additional roles, explained later.
|
||
|
||
|
||
File: m4.info, Node: Input processing, Prev: Other tokens, Up: Syntax
|
||
|
||
3.5 How ‘m4’ copies input to output
|
||
===================================
|
||
|
||
As ‘m4’ reads the input token by token, it will copy each token directly
|
||
to the output immediately.
|
||
|
||
The exception is when it finds a word with a macro definition. In
|
||
that case ‘m4’ will calculate the macro’s expansion, possibly reading
|
||
more input to get the arguments. It then inserts the expansion in front
|
||
of the remaining input. In other words, the resulting text from a macro
|
||
call will be read and parsed into tokens again.
|
||
|
||
‘m4’ expands a macro as soon as possible. If it finds a macro call
|
||
when collecting the arguments to another, it will expand the second call
|
||
first. This process continues until there are no more macro calls to
|
||
expand 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, so it collects
|
||
the tokens ‘(’, ‘`Result is %d'’, ‘,’, and ‘ ’, before encountering
|
||
another potential macro. Sure enough, ‘eval’ is a macro name, so the
|
||
nested argument collection picks up ‘(’, ‘`2**15'’, and ‘)’, invoking
|
||
the eval macro with the lone argument of ‘2**15’. The expansion of
|
||
‘eval(2**15)’ is ‘32768’, which is then rescanned as the five tokens
|
||
‘3’, ‘2’, ‘7’, ‘6’, and ‘8’; and combined with the next ‘)’, the format
|
||
macro now has all its arguments, as if the user had typed:
|
||
|
||
format(`Result is %d', 32768)
|
||
|
||
The format macro expands to ‘Result is 32768’, and we have another round
|
||
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 code
|
||
example from the Gnulib project(1), showing both a buggy approach and
|
||
the desired results. The user desires to output a shell assignment
|
||
statement that takes its argument and turns it into a shell variable by
|
||
converting it to uppercase and prepending a prefix. 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 manual
|
||
is not able to easily show it, both lines that appear empty actually
|
||
contain two trailing spaces. By stepping through the parse, it is easy
|
||
to see what happened. First, ‘m4’ sees the token ‘changequote’, which
|
||
it recognizes as a macro, followed by ‘(’, ‘[’, ‘,’, ‘]’, and ‘)’ to
|
||
form the argument list. The macro expands to the empty string, but
|
||
changes the quoting 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 builtin macro that consumes
|
||
the rest of the line, resulting in no output for that 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 unquoted comma was
|
||
encountered, the first argument is known to be the expansion of the
|
||
single-quoted string token, or ‘gl_STRING_MODULE_INDICATOR’. Next, ‘m4’
|
||
sees ‘<NL>’, ‘ ’, and ‘ ’, but this whitespace is discarded as part of
|
||
argument collection. Then comes a rather lengthy single-quoted string
|
||
token, ‘[<NL> dnl comment<NL> GNULIB_]’. This is followed by the
|
||
token ‘translit’, which ‘m4’ recognizes as a macro name, so a nested
|
||
macro 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’ need capitalization, the result of the macro is
|
||
‘$1’. This expansion is rescanned, 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 of expanded 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’ is recognized as a
|
||
macro name, with an argument list of ‘(’, ‘[strcase]’, and ‘)’. Since
|
||
the definition of the macro contains the sequence ‘$1’, that sequence is
|
||
replaced with the argument ‘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>’. Next comes four more
|
||
spaces, also output literally, and the token ‘GNULIB_strcase’, which
|
||
resulted from the earlier parameter substitution. Since that is not a
|
||
macro name, it is output literally, followed by the literal tokens ‘=’,
|
||
‘1’, ‘<NL>’, and two more spaces. Finally, the original ‘<NL>’ seen
|
||
after the macro invocation is scanned and output literally.
|
||
|
||
Now for a corrected approach. This rearranges the use of newlines
|
||
and whitespace so that less whitespace is output (which, although
|
||
harmless to shell scripts, can be visually unappealing), and fixes the
|
||
quoting issues so that the capitalization occurs when the macro
|
||
‘gl_STRING_MODULE_INDICATOR’ is invoked, rather then when it is defined.
|
||
It also adds another layer of quoting to the first argument of
|
||
‘translit’, to ensure that the output will be rescanned as a string
|
||
rather 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 the
|
||
name 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 the newline. No early expansion of ‘translit’ occurs, so
|
||
the entire string becomes the definition of the macro.
|
||
|
||
The final line is then parsed, beginning with two spaces that are
|
||
output literally, and an invocation of ‘gl_STRING_MODULE_INDICATOR’ with
|
||
the argument ‘strcase’. Again, the ‘$1’ in the macro definition is
|
||
substituted prior to rescanning. Rescanning first encounters ‘dnl’, and
|
||
discards ‘ comment<NL>’. Then two spaces are output literally. Next
|
||
comes the token ‘GNULIB_’, but that is not a macro, so it is output
|
||
literally. The token ‘[]’ is an empty string, so it does not 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 the translit results in the desired result
|
||
‘[STRCASE]’. This is rescanned, but since it is a string, the quotes
|
||
are stripped and the only output is a literal ‘STRCASE’. Then the
|
||
scanner sees ‘=’ and ‘1’, which are output literally, followed by ‘dnl’
|
||
which discards the rest of the definition of
|
||
‘gl_STRING_MODULE_INDICATOR’. The newline at the end of output is the
|
||
literal ‘<NL>’ that appeared after the invocation of the macro.
|
||
|
||
The order in which ‘m4’ expands the macros can be further explored
|
||
using the trace facilities of GNU ‘m4’ (*note Trace::).
|
||
|
||
---------- Footnotes ----------
|
||
|
||
(1) Derived from a patch in
|
||
<https://lists.gnu.org/archive/html/bug-gnulib/2007-01/msg00389.html>,
|
||
and a followup patch in
|
||
<https://lists.gnu.org/archive/html/bug-gnulib/2007-02/msg00000.html>
|
||
|
||
|
||
File: m4.info, Node: Macros, Next: Definitions, Prev: Syntax, Up: Top
|
||
|
||
4 How to invoke macros
|
||
**********************
|
||
|
||
This chapter covers macro invocation, macro arguments and how macro
|
||
expansion is treated.
|
||
|
||
* Menu:
|
||
|
||
* Invocation:: Macro invocation
|
||
* Inhibiting Invocation:: Preventing macro invocation
|
||
* Macro Arguments:: Macro arguments
|
||
* Quoting Arguments:: On Quoting Arguments to macros
|
||
* Macro expansion:: Expanding macros
|
||
|
||
|
||
File: m4.info, Node: Invocation, Next: Inhibiting Invocation, Up: Macros
|
||
|
||
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 any
|
||
number of arguments. All arguments are strings, but different macros
|
||
might interpret the arguments in different ways.
|
||
|
||
The opening parenthesis _must_ follow the NAME directly, with no
|
||
spaces in between. If it does not, the macro is called with no
|
||
arguments at all.
|
||
|
||
For a macro call to have no arguments, the parentheses _must_ be left
|
||
out. The macro call
|
||
|
||
name()
|
||
|
||
is a macro call with one argument, which is the empty string, not a call
|
||
with no arguments.
|
||
|
||
|
||
File: m4.info, Node: Inhibiting Invocation, Next: Macro Arguments, Prev: Invocation, Up: Macros
|
||
|
||
4.2 Preventing macro invocation
|
||
===============================
|
||
|
||
An innovation of the ‘m4’ language, compared to some of its predecessors
|
||
(like Strachey’s ‘GPM’, for example), is the ability to recognize macro
|
||
calls without resorting to any special, prefixed invocation character.
|
||
While generally useful, this feature might sometimes be the source of
|
||
spurious, unwanted macro calls. So, GNU ‘m4’ offers several mechanisms
|
||
or techniques for inhibiting the recognition of names as macro calls.
|
||
|
||
First of all, many builtin macros cannot meaningfully be called
|
||
without arguments. 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 usual
|
||
cases, like for ‘include’ or ‘eval’. Later in this document, the
|
||
sentence “This macro is recognized only with parameters” refers to this
|
||
specific provision of GNU M4, also known as a blind builtin macro. For
|
||
the builtins defined by POSIX that bear this disclaimer, POSIX
|
||
specifically states that invoking those builtins without arguments is
|
||
unspecified, because many other implementations simply invoke the
|
||
builtin as though it were given one empty argument instead.
|
||
|
||
$ m4
|
||
eval
|
||
⇒eval
|
||
eval(`1')
|
||
⇒1
|
||
|
||
There is also a command line option (‘--prefix-builtins’, or ‘-P’,
|
||
*note Invoking m4: Operation modes.) that renames all builtin macros
|
||
with a prefix of ‘m4_’ at startup. The option has no effect whatsoever
|
||
on user defined macros. For example, with this option, one has to write
|
||
‘m4_dnl’ and even ‘m4_m4exit’. It also has no 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 less
|
||
likely to cause conflicts, using *note Definitions::.
|
||
|
||
If your version of GNU ‘m4’ has the ‘changeword’ feature compiled in,
|
||
it offers far more flexibility in specifying the syntax of macro names,
|
||
both builtin or user-defined. *Note Changeword::, for more information
|
||
on this experimental feature.
|
||
|
||
Of course, the simplest way to prevent a name from being interpreted
|
||
as a call to an existing macro is to quote it. The remainder of this
|
||
section studies a little more deeply how quoting affects macro
|
||
invocation, and how quoting can be used to inhibit macro invocation.
|
||
|
||
Even if quoting is usually done over the whole macro name, it can
|
||
also be done over only a few characters of this name (provided, of
|
||
course, that the unquoted portions are not also a macro). It is also
|
||
possible to quote the empty string, but this works only _inside_ 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 the empty
|
||
string.
|
||
|
||
The output of macro evaluations is always rescanned. In the
|
||
following example, the input ‘x`'y’ yields the string ‘bCD’, exactly as
|
||
if ‘m4’ has 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 to
|
||
being recognized as macro names. In the following example, quoting the
|
||
empty string allows for the second ‘macro’ 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
|
||
a macro 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 were
|
||
removed, the ‘divert’ builtin was called instead.
|
||
|
||
|
||
File: m4.info, Node: Macro Arguments, Next: Quoting Arguments, Prev: Inhibiting Invocation, Up: Macros
|
||
|
||
4.3 Macro arguments
|
||
===================
|
||
|
||
When a name is seen, and it has a macro definition, it will be expanded
|
||
as a macro.
|
||
|
||
If the name is followed by an opening parenthesis, the arguments will
|
||
be collected before the macro is called. If too few arguments are
|
||
supplied, the missing arguments are taken to be the empty string.
|
||
However, some builtins are documented to behave differently for a
|
||
missing optional argument than for an explicit empty string. If there
|
||
are too many arguments, the excess arguments are ignored. Unquoted
|
||
leading whitespace is stripped off all arguments, but whitespace
|
||
generated by a macro expansion or occurring after a macro that expanded
|
||
to 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
|
||
⇒
|
||
|
||
Normally ‘m4’ will issue warnings if a builtin macro is called with
|
||
an inappropriate number of arguments, but it can be suppressed with the
|
||
‘--quiet’ command line option (or ‘--silent’, or ‘-Q’, *note Invoking
|
||
m4: Operation modes.). For user defined 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 whatever
|
||
commas, quotes and parentheses that might show up in the resulting
|
||
expanded text will serve to define the arguments as well. Thus, if FOO
|
||
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 contains whitespace, remember that
|
||
unquoted leading whitespace is never part of an argument, but trailing
|
||
whitespace always is.
|
||
|
||
It is possible for a macro’s definition to change during argument
|
||
collection, in which case the expansion uses the definition that was in
|
||
effect 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
|
||
|
||
|
||
File: m4.info, Node: Quoting Arguments, Next: Macro expansion, Prev: Macro Arguments, Up: Macros
|
||
|
||
4.4 On Quoting Arguments to macros
|
||
==================================
|
||
|
||
Each argument has unquoted leading whitespace removed. Within each
|
||
argument, all unquoted parentheses must match. For example, if FOO 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. *Note Pseudo Arguments::, for examples.
|
||
|
||
It is common practice to quote all arguments to macros, unless you
|
||
are sure you want the arguments expanded. Thus, in the above example
|
||
with the parentheses, the ‘right’ way to do it is like this:
|
||
|
||
foo(`() (() (')
|
||
|
||
It is, however, in certain cases necessary (because nested expansion
|
||
must occur to create the arguments for the outer macro) or convenient
|
||
(because it uses fewer characters) to leave out quotes for some
|
||
arguments, and there is nothing wrong in doing it. It just makes life a
|
||
bit harder, if you are not careful to follow a consistent quoting style.
|
||
For consistency, this manual follows the rule of thumb that each layer
|
||
of parentheses introduces another layer of single quoting, except when
|
||
showing the consequences of quoting rules. This is done even when the
|
||
quoted string cannot be a macro, such as with integers when you have not
|
||
changed the syntax via ‘changeword’ (*note Changeword::).
|
||
|
||
The quoting rule of thumb of one level of quoting per parentheses has
|
||
a nice property: when a macro name appears inside parentheses, you can
|
||
determine when it will be expanded. If it is not quoted, it will be
|
||
expanded prior to the outer macro, so that its expansion becomes the
|
||
argument. If it is single-quoted, it will be expanded after the outer
|
||
macro. And if it is double-quoted, it will be used as literal text
|
||
instead 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
|
||
|
||
|
||
File: m4.info, Node: Macro expansion, Prev: Quoting Arguments, Up: Macros
|
||
|
||
4.5 Macro expansion
|
||
===================
|
||
|
||
When the arguments, if any, to a macro call have been collected, the
|
||
macro is expanded, and the expansion text is pushed back onto the input
|
||
(unquoted), and reread. The expansion text from one macro call might
|
||
therefore 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’, and BAR
|
||
expands to ‘Hello’, the input
|
||
|
||
$ m4 -Dbar=Hello -Dfoo=bar
|
||
foo
|
||
⇒Hello
|
||
|
||
will expand first to ‘bar’, and when this is reread and expanded, into
|
||
‘Hello’.
|
||
|
||
|
||
File: m4.info, Node: Definitions, Next: Conditionals, Prev: 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 previous
|
||
value, and bring back the original value at a later time.
|
||
|
||
* Menu:
|
||
|
||
* Define:: Defining a new macro
|
||
* Arguments:: Arguments to macros
|
||
* Pseudo Arguments:: Special arguments to macros
|
||
* Undefine:: Deleting a macro
|
||
* Defn:: Renaming macros
|
||
* Pushdef:: Temporarily redefining macros
|
||
|
||
* Indir:: Indirect call of macros
|
||
* Builtin:: Indirect call of builtins
|
||
|
||
|
||
File: m4.info, Node: Define, Next: Arguments, Up: Definitions
|
||
|
||
5.1 Defining a macro
|
||
====================
|
||
|
||
The normal way to define or redefine macros is to use the builtin
|
||
‘define’:
|
||
|
||
-- Builtin: define (NAME, [EXPANSION])
|
||
Defines NAME to expand to EXPANSION. If EXPANSION 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 not a
|
||
part of the macro definition, and it is consequently copied to the
|
||
output. This can be avoided by use of the macro ‘dnl’. *Note Dnl::,
|
||
for details.
|
||
|
||
The first argument to ‘define’ should be quoted; otherwise, if the
|
||
macro is already defined, you will be defining a different macro. This
|
||
example shows the problems with underquoting, since we did not want to
|
||
redefine ‘one’:
|
||
|
||
define(foo, one)
|
||
⇒
|
||
define(foo, two)
|
||
⇒
|
||
one
|
||
⇒two
|
||
|
||
GNU ‘m4’ normally replaces only the _topmost_ definition of a macro
|
||
if it has several definitions from ‘pushdef’ (*note Pushdef::). Some
|
||
other implementations of ‘m4’ replace all definitions of a macro with
|
||
‘define’. *Note Incompatibilities::, for more details.
|
||
|
||
As a GNU extension, the first argument to ‘define’ does not have to
|
||
be a simple word. It can be any text string, even the empty string. A
|
||
macro with a non-standard name cannot be invoked in the normal way, as
|
||
the name is not recognized. It can only be referenced by the builtins
|
||
‘indir’ (*note Indir::) and ‘defn’ (*note Defn::).
|
||
|
||
Arrays and associative arrays can be simulated by using non-standard
|
||
macro names.
|
||
|
||
-- Composite: array (INDEX)
|
||
-- Composite: array_set (INDEX, [VALUE])
|
||
Provide access to entries within an array. ‘array’ reads the entry
|
||
at location INDEX, and ‘array_set’ assigns VALUE to location 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.
|
||
|
||
|
||
File: m4.info, Node: Arguments, Next: Pseudo Arguments, Prev: Define, Up: Definitions
|
||
|
||
5.2 Arguments to macros
|
||
=======================
|
||
|
||
Macros can have arguments. The Nth argument is denoted by ‘$n’ in the
|
||
expansion text, and is replaced by the Nth actual argument, when the
|
||
macro is expanded. Replacement of arguments happens before rescanning,
|
||
regardless of how many nesting levels of quoting appear in the
|
||
expansion. Here is an example of a macro with two arguments.
|
||
|
||
-- Composite: exch (ARG1, ARG2)
|
||
Expands to ARG2 followed by ARG1, effectively exchanging their
|
||
order.
|
||
|
||
define(`exch', `$2, $1')
|
||
⇒
|
||
exch(`arg1', `arg2')
|
||
⇒arg2, arg1
|
||
|
||
This can be used, for example, if you like the arguments to ‘define’
|
||
to be reversed.
|
||
|
||
define(`exch', `$2, $1')
|
||
⇒
|
||
define(exch(``expansion text'', ``macro''))
|
||
⇒
|
||
macro
|
||
⇒expansion text
|
||
|
||
*Note Quoting Arguments::, for an explanation of the double quotes.
|
||
(You should try and improve this example so that clients of ‘exch’ do
|
||
not have to double quote; or *note Answers: Improved exch.).
|
||
|
||
As a special case, the zeroth argument, ‘$0’, is always the name of
|
||
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 is _not_ expanded, since it is a quoted
|
||
string, and not a name.
|
||
|
||
GNU ‘m4’ allows the number following the ‘$’ to consist of one or
|
||
more digits, allowing macros to have any number of arguments. The
|
||
extension of accepting multiple digits is incompatible with POSIX, and
|
||
is different than traditional implementations of ‘m4’, which only
|
||
recognize one digit. Therefore, future versions of GNU M4 will phase
|
||
out this feature. To portably access beyond the ninth argument, you can
|
||
use the ‘argn’ macro documented later (*note Shift::).
|
||
|
||
POSIX also states that ‘$’ followed immediately by ‘{’ in a macro
|
||
definition is implementation-defined. This version of M4 passes the
|
||
literal characters ‘${’ through unchanged, but M4 2.0 will implement an
|
||
optional feature similar to ‘sh’, where ‘${11}’ expands to the eleventh
|
||
argument, to replace the current recognition of ‘$11’. Meanwhile, if
|
||
you want to guarantee that you will get a literal ‘${’ in output when
|
||
expanding a macro, even when you upgrade to M4 2.0, you can use nested
|
||
quoting to your advantage:
|
||
|
||
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 in
|
||
behavior due to the changed behavior of M4 2.0, you can use the
|
||
‘--warn-macro-sequence’ command-line option (*note Invoking m4:
|
||
Operation modes.) with the default regular expression. This will add a
|
||
warning any time a macro definition includes ‘$’ followed by multiple
|
||
digits, or by ‘{’. The warning is not enabled by default, because it
|
||
triggers a number of warnings in Autoconf 2.61 (and Autoconf uses ‘-E’
|
||
to treat warnings as errors), and because it will 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
|
||
|
||
|
||
File: m4.info, Node: Pseudo Arguments, Next: Undefine, Prev: 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 forget
|
||
quotes to inhibit the comment behavior, your macro definition may not
|
||
end 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 all the
|
||
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 ‘$@’ handles
|
||
that. 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
|
||
expanded text were reread by ‘m4’. 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
|
||
|
||
*Note Trace::, if you do not understand this. As another example of the
|
||
difference, remember that comments encountered in arguments are passed
|
||
untouched 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 anything
|
||
‘m4’ understands, is simply copied to the macro expansion, as any other
|
||
text is.
|
||
|
||
define(`foo', `$$$ hello $$$')
|
||
⇒
|
||
foo
|
||
⇒$$$ hello $$$
|
||
|
||
If you want a macro to expand to something like ‘$12’, the judicious
|
||
use of nested quoting can put a safe character between the ‘$’ and the
|
||
next character, relying on the rescanning to remove the nested quote.
|
||
This will prevent ‘m4’ 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
|
||
|
||
|
||
File: m4.info, Node: Undefine, Next: Defn, Prev: Pseudo Arguments, Up: Definitions
|
||
|
||
5.4 Deleting a macro
|
||
====================
|
||
|
||
A macro definition can be removed with ‘undefine’:
|
||
|
||
-- Builtin: undefine (NAME...)
|
||
For each argument, remove the macro NAME. The macro names must
|
||
necessarily 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 macro
|
||
still 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 that
|
||
case, ‘undefine’ does nothing.
|
||
|
||
|
||
File: m4.info, Node: Defn, Next: Pushdef, Prev: Undefine, Up: Definitions
|
||
|
||
5.5 Renaming macros
|
||
===================
|
||
|
||
It is possible to rename an already defined macro. To do this, you need
|
||
the builtin ‘defn’:
|
||
|
||
-- Builtin: defn (NAME...)
|
||
Expands to the _quoted definition_ of each NAME. If an argument is
|
||
not a defined macro, the expansion for that argument is empty.
|
||
|
||
If NAME is a user-defined macro, the quoted definition is simply
|
||
the quoted expansion text. If, instead, there is only one NAME and
|
||
it is a builtin, the expansion is a special token, which points to
|
||
the builtin’s internal definition. This token is only meaningful
|
||
as the second argument to ‘define’ (and ‘pushdef’), and is silently
|
||
converted to an empty string in most other contexts. Combining a
|
||
builtin with anything else is not supported; a warning is issued
|
||
and the builtin is omitted from the final expansion.
|
||
|
||
The macro ‘defn’ is recognized only with parameters.
|
||
|
||
Its normal use is best understood through an example, which shows how
|
||
to rename ‘undefine’ to ‘zap’:
|
||
|
||
define(`zap', defn(`undefine'))
|
||
⇒
|
||
zap(`undefine')
|
||
⇒
|
||
undefine(`zap')
|
||
⇒undefine(zap)
|
||
|
||
In this way, ‘defn’ can be used to copy macro definitions, and also
|
||
definitions 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
|
||
you should use ‘$0’, rather than retyping a macro’s name in its
|
||
definition:
|
||
|
||
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 purely
|
||
textual. If an unbalanced end-quote string occurs in a macro
|
||
definition, the rescan will see that embedded quote as the termination
|
||
of the quoted string, and the remainder of the macro’s definition will
|
||
be rescanned unquoted. Thus it is a good idea to avoid unbalanced
|
||
end-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 ‘defn’ can
|
||
concatenate multiple macros prior to the rescanning phase, in order to
|
||
join the definitions of macros that, in isolation, have unbalanced
|
||
quotes. This is particularly useful when one has used several macros to
|
||
accumulate text that M4 should rescan as a whole. In the example below,
|
||
note how the use of ‘defn’ on ‘l’ in isolation opens a string, which is
|
||
not closed until the next line; but used on ‘l’ and ‘r’ together results
|
||
in nested quoting.
|
||
|
||
define(`l', `<[>')define(`r', `<]>')
|
||
⇒
|
||
changequote(`[', `]')
|
||
⇒
|
||
defn([l])defn([r])
|
||
])
|
||
⇒<[>]defn([r])
|
||
⇒)
|
||
defn([l], [r])
|
||
⇒<[>][<]>
|
||
|
||
Using ‘defn’ to generate special tokens for builtin macros outside of
|
||
expected contexts can sometimes trigger warnings. But most of the time,
|
||
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 text
|
||
macros, not builtins, although a future version of GNU M4 may lift 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')
|
||
⇒
|
||
|
||
|
||
File: m4.info, Node: Pushdef, Next: Indir, Prev: Defn, Up: Definitions
|
||
|
||
5.6 Temporarily redefining macros
|
||
=================================
|
||
|
||
It is possible to redefine a macro temporarily, reverting to the
|
||
previous definition at a later time. This is done with the builtins
|
||
‘pushdef’ and ‘popdef’:
|
||
|
||
-- Builtin: pushdef (NAME, [EXPANSION])
|
||
-- Builtin: popdef (NAME...)
|
||
Analogous to ‘define’ and ‘undefine’.
|
||
|
||
These macros work in a stack-like fashion. A macro is temporarily
|
||
redefined with ‘pushdef’, which replaces an existing definition of
|
||
NAME, while saving the previous definition, before the new one is
|
||
installed. If there is no previous definition, ‘pushdef’ behaves
|
||
exactly like ‘define’.
|
||
|
||
If a macro has several definitions (of which only one is
|
||
accessible), the topmost definition can be removed with ‘popdef’.
|
||
If there is no previous definition, ‘popdef’ behaves like
|
||
‘undefine’.
|
||
|
||
The expansion of both ‘pushdef’ and ‘popdef’ is void. The macros
|
||
‘pushdef’ and ‘popdef’ are recognized only with parameters.
|
||
|
||
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’, the
|
||
topmost definition is _replaced_ with the new definition. If it is
|
||
removed with ‘undefine’, _all_ the definitions are removed, and not only
|
||
the topmost one. However, POSIX allows other implementations that treat
|
||
‘define’ as replacing an entire stack of definitions with a single new
|
||
definition, so to be portable to other implementations, it may be worth
|
||
explicitly using ‘popdef’ and ‘pushdef’ rather than relying on the GNU
|
||
behavior of ‘define’.
|
||
|
||
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 with ‘pushdef’ and ‘popdef’.
|
||
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 ‘pushdef’ and
|
||
‘defn’.
|
||
|
||
|
||
File: m4.info, Node: Indir, Next: Builtin, Prev: Pushdef, Up: Definitions
|
||
|
||
5.7 Indirect call of macros
|
||
===========================
|
||
|
||
Any macro can be called indirectly with ‘indir’:
|
||
|
||
-- Builtin: indir (NAME, [ARGS...])
|
||
Results in a call to the macro NAME, which is passed the rest of
|
||
the arguments ARGS. If NAME is not defined, an error 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
|
||
macros defined, that will not be called by accident. They can _only_ be
|
||
called through the builtin ‘indir’.
|
||
|
||
One other point to observe is that argument collection occurs before
|
||
‘indir’ invokes NAME, so if argument collection changes the value 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 is used.
|
||
|
||
$ 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’ (*note Defn::) as one of its
|
||
arguments, ‘indir’ defers to the invoked NAME for whether a token
|
||
representing a builtin is recognized or flattened to the empty string.
|
||
|
||
$ 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'
|
||
⇒
|
||
|
||
|
||
File: m4.info, Node: Builtin, Prev: Indir, Up: Definitions
|
||
|
||
5.8 Indirect call of builtins
|
||
=============================
|
||
|
||
Builtin macros can be called indirectly with ‘builtin’:
|
||
|
||
-- Builtin: builtin (NAME, [ARGS...])
|
||
Results in a call to the builtin NAME, which is passed the rest of
|
||
the arguments ARGS. If NAME does not name a builtin, 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 definition that
|
||
has covered the original, or been undefined so that no macro maps 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’, *note Invoking m4:
|
||
Operation modes.) is in effect. This is different from ‘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 builtins
|
||
without arguments, even when they normally require parameters to be
|
||
recognized; 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'
|
||
⇒
|
||
|
||
|
||
File: m4.info, Node: Conditionals, Next: Debugging, Prev: Definitions, Up: Top
|
||
|
||
6 Conditionals, loops, and recursion
|
||
************************************
|
||
|
||
Macros, expanding to plain text, perhaps with arguments, are not quite
|
||
enough. We would like to have macros expand to different things, based
|
||
on 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 do something a number of times, or while some condition is
|
||
true.
|
||
|
||
* Menu:
|
||
|
||
* Ifdef:: Testing if a macro is defined
|
||
* Ifelse:: If-else construct, or multibranch
|
||
* Shift:: Recursion in ‘m4’
|
||
* Forloop:: Iteration by counting
|
||
* Foreach:: Iteration by list contents
|
||
* Stacks:: Working with definition stacks
|
||
* Composition:: Building macros with macros
|
||
|
||
|
||
File: m4.info, Node: Ifdef, Next: Ifelse, Up: Conditionals
|
||
|
||
6.1 Testing if a macro is defined
|
||
=================================
|
||
|
||
There are two different builtin conditionals in ‘m4’. The first is
|
||
‘ifdef’:
|
||
|
||
-- Builtin: ifdef (NAME, STRING-1, [STRING-2])
|
||
If NAME is defined as a macro, ‘ifdef’ expands to STRING-1,
|
||
otherwise to STRING-2. If STRING-2 is omitted, it is taken to be
|
||
the empty string (according to the normal rules).
|
||
|
||
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
|
||
|
||
|
||
File: m4.info, Node: Ifelse, Next: Shift, Prev: Ifdef, Up: Conditionals
|
||
|
||
6.2 If-else construct, or multibranch
|
||
=====================================
|
||
|
||
The other conditional, ‘ifelse’, is much more powerful. It can be used
|
||
as a way to introduce a long comment, as an if-else construct, or as 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 and
|
||
produces no output.
|
||
|
||
If called with three or four arguments, ‘ifelse’ expands into
|
||
EQUAL, if STRING-1 and STRING-2 are equal (character for
|
||
character), otherwise it expands to NOT-EQUAL. A final fifth
|
||
argument is ignored, after triggering a warning.
|
||
|
||
If called with six or more arguments, and STRING-1 and STRING-2 are
|
||
equal, ‘ifelse’ expands into EQUAL-1, otherwise the first three
|
||
arguments are discarded and the processing starts again.
|
||
|
||
The macro ‘ifelse’ is recognized only with parameters.
|
||
|
||
Using only one argument is a common ‘m4’ idiom for introducing a
|
||
block comment, as an alternative to repeatedly using ‘dnl’. This
|
||
special usage is recognized by GNU ‘m4’, so that in this case, 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
|
||
compare the expansion of a macro with a string. With this macro, you
|
||
can now reproduce the behavior of blind builtins, where the macro is
|
||
recognized only 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, see
|
||
*note Composition::.
|
||
|
||
The macro ‘ifelse’ can take more than four arguments. If given more
|
||
than four arguments, ‘ifelse’ works like a ‘case’ or ‘switch’ statement
|
||
in traditional programming languages. If STRING-1 and STRING-2 are
|
||
equal, ‘ifelse’ expands into EQUAL-1, otherwise the procedure is
|
||
repeated with the first three arguments discarded. This calls 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 these
|
||
examples. A common use of ‘ifelse’ is in macros implementing loops of
|
||
various kinds.
|
||
|
||
|
||
File: m4.info, Node: Shift, Next: Forloop, Prev: Ifelse, Up: Conditionals
|
||
|
||
6.3 Recursion in ‘m4’
|
||
=====================
|
||
|
||
There is no direct support for loops in ‘m4’, but macros can be
|
||
recursive. There is no limit on the number of recursion levels, other
|
||
than those enforced by your hardware and operating system.
|
||
|
||
Loops can be programmed using recursion and the conditionals
|
||
described previously.
|
||
|
||
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
|
||
except ARG1, 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
|
||
be made with ‘shift’, ‘ifelse’ and recursion. It also shows that
|
||
‘shift’ is usually used with ‘$@’. Another example of this 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 first
|
||
two strings results in the third, otherwise the first three
|
||
arguments are discarded and the process repeats. The difference is
|
||
that each TEST-<N> is expanded only when it is encountered. This
|
||
means that every third argument to ‘cond’ is normally given one
|
||
more level of quoting than the corresponding argument to ‘ifelse’.
|
||
|
||
Here is the implementation of ‘cond’, along with a demonstration of
|
||
how it can short-circuit the side effects in ‘side’. Notice how all the
|
||
unquoted side effects happen regardless of how many comparisons are made
|
||
with ‘ifelse’, compared with only the relevant effects with ‘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 of
|
||
arguments into a single string.
|
||
|
||
-- Composite: join ([SEPARATOR], [ARGS...])
|
||
-- Composite: joinall ([SEPARATOR], [ARGS...])
|
||
Generate a single-quoted string, consisting of each ARG separated
|
||
by SEPARATOR. While ‘joinall’ always outputs a SEPARATOR between
|
||
arguments, ‘join’ avoids the SEPARATOR for an empty ARG.
|
||
|
||
Here are some examples of its usage, based on the implementation
|
||
‘m4-1.4.19/examples/join.m4’ distributed in this package:
|
||
|
||
$ 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
|
||
several m4 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 it easier to output the
|
||
correct number of SEPARATOR instances: ‘join’ and ‘joinall’ are
|
||
responsible for the first argument, without a separator, while ‘_join’
|
||
and ‘_joinall’ are responsible for all remaining arguments, always
|
||
outputting a separator when outputting an argument.
|
||
|
||
Next, observe how ‘join’ decides to iterate to itself, because the
|
||
first ARG was empty, or to output the argument and swap over to ‘_join’.
|
||
If the argument is non-empty, then the nested ‘ifelse’ results in an
|
||
unquoted ‘_’, which is concatenated with the ‘$0’ to form the next macro
|
||
name to invoke. The ‘joinall’ implementation is simpler since it does
|
||
not have to suppress empty ARG; it always executes once then defers to
|
||
‘_joinall’.
|
||
|
||
Another important idiom is the idea that SEPARATOR is reused for each
|
||
iteration. Each iteration has one less argument, but rather than
|
||
discarding ‘$1’ by iterating with ‘$0(shift($@))’, the macro discards
|
||
‘$2’ by using ‘$0(`$1', shift(shift($@)))’.
|
||
|
||
Next, notice that it is possible to compare more than one condition
|
||
in a single ‘ifelse’ test. The test of ‘$#$2’ against ‘2’ allows
|
||
‘_join’ to iterate for two separate reasons—either there are still more
|
||
than two arguments, or there are exactly two arguments but the last
|
||
argument is not empty.
|
||
|
||
Finally, notice that these macros require exactly two arguments to
|
||
terminate recursion, but that they still correctly result in empty
|
||
output when given no ARGS (i.e., zero or one macro argument). On the
|
||
first pass when there are too few arguments, the ‘shift’ results in no
|
||
output, but leaves an empty string to serve as the required second
|
||
argument for the second pass. Put another way, ‘`$1', shift($@)’ is not
|
||
the same as ‘$@’, since only the former 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 whitespace
|
||
after commas and turning multiple arguments into a single string.
|
||
With ‘dquote’, two levels of quoting are added, one around each
|
||
element, and one around the list. And with ‘dquote_elt’, two
|
||
levels of quoting are added around each element.
|
||
|
||
An actual implementation of these three macros is distributed as
|
||
‘m4-1.4.19/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, ‘dquote’
|
||
results in one string, while ‘dquote_elt’ results in two. Now, examine
|
||
the implementation. Note that ‘quote’ and ‘dquote_elt’ make decisions
|
||
based on their number of arguments, so that when called without
|
||
arguments, they result in nothing instead of a quoted empty string; this
|
||
is so that it is possible to distinguish between no arguments and an
|
||
empty first argument. ‘dquote’, on the other hand, results in a string
|
||
no matter what, since it is still possible to tell whether it was
|
||
invoked without arguments based on the resulting 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 efficient than
|
||
‘joinall(`,', ARGS)’ for producing the same output.
|
||
|
||
One more useful macro based on ‘shift’ allows portably selecting an
|
||
arbitrary argument (usually greater than the ninth argument), without
|
||
relying on the GNU extension of multi-digit arguments (*note
|
||
Arguments::).
|
||
|
||
-- Composite: argn (N, ...)
|
||
Expands to argument N out of the remaining arguments. N must 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
|
||
|
||
|
||
File: m4.info, Node: Forloop, Next: Foreach, Prev: 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, and
|
||
successively assign it each integer value from START to END,
|
||
inclusive. For each assignment to ITERATOR, append TEXT to the
|
||
expansion of the ‘forloop’. TEXT may refer to ITERATOR. Any
|
||
definition of ITERATOR prior to this invocation 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 fairly straightforward.
|
||
The ‘forloop’ macro itself is simply a wrapper, which saves the previous
|
||
definition of the first argument, calls the internal macro ‘_forloop’,
|
||
and re-establishes the saved definition of the first argument.
|
||
|
||
The macro ‘_forloop’ expands the fourth argument once, and tests to
|
||
see if the iterator has reached the final value. If it has not
|
||
finished, it increments the iterator (using the predefined macro ‘incr’,
|
||
*note Incr::), and recurses.
|
||
|
||
Here is an actual implementation of ‘forloop’, distributed as
|
||
‘m4-1.4.19/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 left
|
||
unquoted, each for its own reason. Try to find out _why_ these
|
||
arguments are left unquoted, and see what happens if they are quoted.
|
||
(As presented, these two macros are useful but not very robust for
|
||
general use. They lack even basic error handling for cases like START
|
||
less than END, END not numeric, or ITERATOR not being a macro name. See
|
||
if you can improve these macros; or *note Answers: Improved forloop.).
|
||
|
||
|
||
File: m4.info, Node: Foreach, Next: Stacks, Prev: 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, and
|
||
successively assign it each value from PAREN-LIST or QUOTE-LIST.
|
||
In ‘foreach’, PAREN-LIST is a comma-separated list of elements
|
||
contained in parentheses. In ‘foreachq’, QUOTE-LIST is a
|
||
comma-separated list of elements contained in a quoted string. For
|
||
each assignment to ITERATOR, append TEXT to the overall expansion.
|
||
TEXT may refer to ITERATOR. Any definition of ITERATOR prior to
|
||
this invocation is restored.
|
||
|
||
As an example, this displays each word in a list inside of a
|
||
sentence, using an implementation of ‘foreach’ distributed as
|
||
‘m4-1.4.19/examples/foreach.m4’, and ‘foreachq’ in
|
||
‘m4-1.4.19/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-LIST or
|
||
QUOTE-LIST can itself be a list, to pass as further arguments to 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’ is needed to grab
|
||
the first element of a list. Second, ‘_foreach’ implements the
|
||
recursion, successively walking through the original list. Here is a
|
||
simple implementation of ‘foreach’:
|
||
|
||
$ 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
|
||
list elements. Each iteration of ‘_foreach’ is stripping another layer
|
||
of quotes, leading to erratic results if list elements are not already
|
||
fully expanded. The first cut at implementing ‘foreachq’ takes this
|
||
into account. Also, when using quoted elements in a PAREN-LIST, the
|
||
overall list must be quoted. A QUOTE-LIST has the nice property of
|
||
requiring fewer characters to create a list containing the same quoted
|
||
elements. To see the difference between the two macros, we attempt to
|
||
pass double-quoted macro names in a list, expecting the macro name on
|
||
output after one layer of quotes is removed during list iteration and
|
||
the final layer removed during the final rescan:
|
||
|
||
$ 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 macro ‘quote’ defined
|
||
earlier (*note Shift::), to ensure that the embedded ‘ifelse’ call does
|
||
not go haywire if a list element contains a comma. Unfortunately, this
|
||
implementation of ‘foreachq’ has its own severe flaw. Whereas the
|
||
‘foreach’ implementation was linear, this macro is quadratic in the
|
||
number of list elements, and is much more likely to trip up the limit
|
||
set by the command line option ‘--nesting-limit’ (or ‘-L’, *note
|
||
Invoking m4: Limits control.). Additionally, this implementation does
|
||
not expand ‘defn(`ITERATOR')’ very well, when compared with ‘foreach’.
|
||
|
||
$ 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 sane
|
||
ITERATOR contents for either list style. See if you can learn from the
|
||
best elements of both of these implementations to create robust macros
|
||
(or *note Answers: Improved foreach.).
|
||
|
||
|
||
File: m4.info, Node: Stacks, Next: Composition, Prev: Foreach, Up: Conditionals
|
||
|
||
6.6 Working with definition stacks
|
||
==================================
|
||
|
||
Thanks to ‘pushdef’, manipulation of a stack is an intrinsic operation
|
||
in ‘m4’. Normally, only the topmost definition in a stack is important,
|
||
but sometimes, it is desirable to manipulate the entire definition
|
||
stack.
|
||
|
||
-- Composite: stack_foreach (MACRO, ACTION)
|
||
-- Composite: stack_foreach_lifo (MACRO, ACTION)
|
||
For each of the ‘pushdef’ definitions associated with MACRO, invoke
|
||
the macro ACTION with a single argument of that definition.
|
||
‘stack_foreach’ visits the oldest definition first, while
|
||
‘stack_foreach_lifo’ visits the current definition first. ACTION
|
||
should not modify or dereference MACRO. There are a few special
|
||
macros, such as ‘defn’, which cannot be used as the MACRO
|
||
parameter.
|
||
|
||
A sample implementation of these macros is distributed in the file
|
||
‘m4-1.4.19/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 one stack of
|
||
definitions into the reverse order in the temporary macro ‘tmp-$1’. By
|
||
calling the helper twice, the original order is restored back into the
|
||
macro ‘$1’; since the operation is destructive, this explains why ‘$1’
|
||
must not be modified or dereferenced during the traversal. The caller
|
||
can then inject additional code to pass the definition currently being
|
||
visited to ‘$2’. The choice of helper names is intentional; since ‘-’
|
||
is not valid as part of a macro name, there is no risk of conflict with
|
||
a valid macro name, and the code is guaranteed to use ‘defn’ where
|
||
necessary. Finally, note that any macro used in the traversal of a
|
||
‘pushdef’ stack, such as ‘pushdef’ or ‘defn’, cannot be handled by
|
||
‘stack_foreach’, since the macro would temporarily be undefined 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
|
||
|
||
|
||
File: m4.info, Node: Composition, Prev: Stacks, Up: Conditionals
|
||
|
||
6.7 Building macros with macros
|
||
===============================
|
||
|
||
Since m4 is a macro language, it is possible to write macros that can
|
||
build other macros. First on the list is a way to automate the creation
|
||
of blind macros.
|
||
|
||
-- Composite: define_blind (NAME, [VALUE])
|
||
Defines NAME as a blind macro, such that NAME will expand to VALUE
|
||
only when given explicit arguments. VALUE should not be the result
|
||
of ‘defn’ (*note Defn::). This macro is only recognized with
|
||
parameters, and results in an empty string.
|
||
|
||
Defining a macro to define another macro can be a bit tricky. We
|
||
want to use a literal ‘$#’ in the argument to the nested ‘define’.
|
||
However, if ‘$’ and ‘#’ are adjacent in the definition of
|
||
‘define_blind’, then it would be expanded as the number of arguments to
|
||
‘define_blind’ rather than the intended number of arguments to NAME.
|
||
The solution is to pass the difficult characters through extra arguments
|
||
to a helper macro ‘_define_blind’. When composing macros, it is a
|
||
common idiom to need a helper macro to concatenate text that forms
|
||
parameters in the composed macro, rather than interpreting the text as a
|
||
parameter of the composing macro.
|
||
|
||
As for the limitation against using ‘defn’, there are two reasons.
|
||
If a macro was previously defined with ‘define_blind’, then it can
|
||
safely be renamed to a new blind macro using plain ‘define’; using
|
||
‘define_blind’ to rename it just adds another layer of ‘ifelse’,
|
||
occupying memory and slowing down execution. And if a macro is a
|
||
builtin, then it would result in an attempt to define a macro consisting
|
||
of both text and a builtin token; this is not supported, and the builtin
|
||
token is flattened to an empty string.
|
||
|
||
With that explanation, here’s the definition, and some sample usage.
|
||
Notice that ‘define_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 argument “currying”, or
|
||
factoring a macro that takes multiple arguments for use in a context
|
||
that provides exactly one argument.
|
||
|
||
-- Composite: curry (MACRO, ...)
|
||
Expand to a macro call that takes exactly one argument, then
|
||
appends that argument to the original arguments and invokes MACRO
|
||
with the resulting list of arguments.
|
||
|
||
A demonstration of currying makes the intent of this macro a little
|
||
more obvious. The macro ‘stack_foreach’ mentioned earlier is an example
|
||
of a context that provides exactly one argument to a macro name. But
|
||
coupled with currying, we can invoke ‘reverse’ with two arguments for
|
||
each definition of a macro stack. This example uses the file
|
||
‘m4-1.4.19/examples/curry.m4’ included in the distribution.
|
||
|
||
$ 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 a
|
||
macro name but no open parenthesis, while still in the middle of
|
||
collecting arguments for ‘$1’. The macro ‘_curry’ is the helper macro
|
||
that takes one argument, then adds it to the list and finally supplies
|
||
the closing parenthesis. The use of a comma inside the ‘shift’ call
|
||
allows currying to also work for a macro that takes one argument,
|
||
although it often makes more sense to invoke that macro directly rather
|
||
than going through ‘curry’.
|
||
|
||
$ 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 builtin
|
||
tokens, which are silently flattened to the empty string when passed
|
||
through another text macro. This limitation will be lifted in a future
|
||
release of M4.
|
||
|
||
Putting the last few concepts together, it is possible to copy or
|
||
rename an 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 of
|
||
definitions currently in SOURCE. ‘copy’ leaves SOURCE unchanged,
|
||
while ‘rename’ undefines SOURCE. There are only a few macros, such
|
||
as ‘copy’ or ‘defn’, which cannot be copied via this macro.
|
||
|
||
The implementation is relatively straightforward (although since it
|
||
uses ‘curry’, it is unable to copy builtin macros, such as the second
|
||
definition of ‘a’ as a synonym for ‘divnum’. See if you can design a
|
||
version that works around this limitation, or *note Answers: Improved
|
||
copy.).
|
||
|
||
$ 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
|
||
|
||
|
||
File: m4.info, Node: Debugging, Next: Input Control, Prev: Conditionals, Up: Top
|
||
|
||
7 How to debug macros and input
|
||
*******************************
|
||
|
||
When writing macros for ‘m4’, they often do not work as intended on the
|
||
first try (as is the case with most programming languages).
|
||
Fortunately, there is support for macro debugging in ‘m4’.
|
||
|
||
* Menu:
|
||
|
||
* Dumpdef:: Displaying macro definitions
|
||
* Trace:: Tracing macro calls
|
||
* Debug Levels:: Controlling debugging output
|
||
* Debug Output:: Saving debugging output
|
||
|
||
|
||
File: m4.info, Node: Dumpdef, Next: Trace, Up: Debugging
|
||
|
||
7.1 Displaying macro definitions
|
||
================================
|
||
|
||
If you want to see what a name expands into, you can use the builtin
|
||
‘dumpdef’:
|
||
|
||
-- Builtin: dumpdef ([NAMES...])
|
||
Accepts any number of arguments. If called without any arguments,
|
||
it displays the definitions of all known names, otherwise it
|
||
displays the definitions of the NAMES given. The output is printed
|
||
to the current debug file (usually standard error), and is sorted
|
||
by name. If an unknown name is encountered, a warning is printed.
|
||
|
||
The expansion of ‘dumpdef’ is void.
|
||
|
||
$ m4 -d
|
||
define(`foo', `Hello world.')
|
||
⇒
|
||
dumpdef(`foo')
|
||
error→foo: ⇒
|
||
dumpdef(`define')
|
||
error→define: ⇒
|
||
|
||
The last example shows how builtin macros definitions are displayed.
|
||
The definition that is dumped corresponds to what would occur if the
|
||
macro were to be called at that point, even if other definitions are
|
||
still 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: ⇒f2
|
||
f(popdef(`f')dumpdef(`f'))
|
||
error→m4:stdin:3: undefined macro `f'
|
||
⇒f1
|
||
|
||
*Note Debug Levels::, for information on controlling the details of
|
||
the display.
|
||
|
||
|
||
File: m4.info, Node: Trace, Next: Debug Levels, Prev: Dumpdef, Up: Debugging
|
||
|
||
7.2 Tracing macro calls
|
||
=======================
|
||
|
||
It is possible to trace macro calls and expansions through the builtins
|
||
‘traceon’ and ‘traceoff’:
|
||
|
||
-- Builtin: traceon ([NAMES...])
|
||
-- Builtin: traceoff ([NAMES...])
|
||
When called without any arguments, ‘traceon’ and ‘traceoff’ will
|
||
turn tracing on and off, respectively, for all currently defined
|
||
macros.
|
||
|
||
When called with arguments, only the macros listed in NAMES are
|
||
affected, 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
|
||
printed to the current debug file (defaulting to standard error, *note
|
||
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
|
||
most of the time, signifying an expansion at the outermost level, but it
|
||
increases when macro arguments contain unquoted macro calls. The
|
||
maximum number that will appear between dashes is controlled by the
|
||
option ‘--nesting-limit’ (or ‘-L’, *note Invoking m4: Limits control.).
|
||
Additionally, the option ‘--trace’ (or ‘-t’) can be used to invoke
|
||
‘traceon(NAME)’ before parsing 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
|
||
is defined or not. This allows the selection of macros to trace before
|
||
those 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’ (*note 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
|
||
|
||
*Note Debug Levels::, for information on controlling the details of
|
||
the display. The format of the trace output is not specified by POSIX,
|
||
and varies between implementations of ‘m4’.
|
||
|
||
|
||
File: m4.info, Node: Debug Levels, Next: Debug Output, Prev: Trace, Up: Debugging
|
||
|
||
7.3 Controlling debugging output
|
||
================================
|
||
|
||
The ‘-d’ option to ‘m4’ (or ‘--debug’, *note Invoking m4: Debugging
|
||
options.) controls the amount of details presented in three categories
|
||
of output. Trace output is requested by ‘traceon’ (*note Trace::), and
|
||
each line is prefixed by ‘m4trace:’ in relation to a macro invocation.
|
||
Debug output tracks useful events not associated with a macro
|
||
invocation, and each line is prefixed by ‘m4debug:’. Finally, ‘dumpdef’
|
||
(*note Dumpdef::) output is affected, with no prefix added to the output
|
||
lines.
|
||
|
||
The FLAGS following the option can be one or more of the following:
|
||
|
||
‘a’
|
||
In trace output, show the actual arguments that were collected
|
||
before invoking 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 by
|
||
the command line option ‘--arglength’ (or ‘-l’).
|
||
|
||
‘c’
|
||
In trace output, show several trace lines for each macro call. A
|
||
line is shown when the macro is seen, but before the arguments are
|
||
collected; a second line when the arguments have been collected and
|
||
a third line after the call has completed.
|
||
|
||
‘e’
|
||
In trace output, show the expansion of each macro call, if it is
|
||
not void. This applies to all macro calls if the ‘t’ flag is used,
|
||
otherwise only the macros covered by calls of ‘traceon’. The
|
||
expansion is subject to length truncation specified by the command
|
||
line option ‘--arglength’ (or ‘-l’).
|
||
|
||
‘f’
|
||
In debug and trace output, include the name of the current input
|
||
file in the output line.
|
||
|
||
‘i’
|
||
In debug output, print a message each time the current input file
|
||
is changed.
|
||
|
||
‘l’
|
||
In debug and trace output, include the current input line number in
|
||
the output line.
|
||
|
||
‘p’
|
||
In debug output, print a message when a named file is found through
|
||
the path search mechanism (*note Search Path::), giving the actual
|
||
file name used.
|
||
|
||
‘q’
|
||
In trace and dumpdef output, quote actual arguments and macro
|
||
expansions in the display with the current quotes. This is useful
|
||
in connection with 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
|
||
trace output. 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 default flags.
|
||
|
||
There is a builtin macro ‘debugmode’, which allows on-the-fly control
|
||
of the 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 are
|
||
added to the current debug flags, and if it starts with a ‘-’, they
|
||
are removed. If no argument is present, all debugging flags are
|
||
cleared (as if no ‘-d’ was given), and with an empty argument the
|
||
flags are 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 the
|
||
final result are individually truncated. Also, the special tokens for
|
||
builtin 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
|
||
related to 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
|
||
|
||
|
||
File: m4.info, Node: Debug Output, Prev: 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’ (*note Invoking m4: Debugging options.), or
|
||
with the builtin macro ‘debugfile’:
|
||
|
||
-- Builtin: debugfile ([FILE])
|
||
Sends all further debug and trace output to FILE, opened in append
|
||
mode. If FILE is the empty string, debug and trace output are
|
||
discarded. If ‘debugfile’ is called without any arguments, debug
|
||
and trace output are sent to standard error. This does not affect
|
||
warnings, error messages, or ‘errprint’ output, which are always
|
||
sent to standard error. If FILE cannot be opened, the current
|
||
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
|
||
|
||
|
||
File: m4.info, Node: Input Control, Next: File Inclusion, Prev: Debugging, Up: Top
|
||
|
||
8 Input control
|
||
***************
|
||
|
||
This chapter describes various builtin macros for controlling the input
|
||
to ‘m4’.
|
||
|
||
* Menu:
|
||
|
||
* Dnl:: Deleting whitespace in input
|
||
* Changequote:: Changing the quote characters
|
||
* Changecom:: Changing the comment delimiters
|
||
* Changeword:: Changing the lexical structure of words
|
||
* M4wrap:: Saving text until end of input
|
||
|
||
|
||
File: m4.info, Node: Dnl, Next: Changequote, Up: Input Control
|
||
|
||
8.1 Deleting whitespace in input
|
||
================================
|
||
|
||
The builtin ‘dnl’ stands for “Discard to Next Line”:
|
||
|
||
-- Builtin: dnl
|
||
All characters, up to and including the next newline, are discarded
|
||
without performing any macro expansion. A warning is issued if the
|
||
end of the file is encountered without a newline.
|
||
|
||
The expansion of ‘dnl’ is void.
|
||
|
||
It is often used in connection with ‘define’, to remove the newline
|
||
that follows the call to ‘define’. 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
|
||
opposed to the way comments are treated (*note Comments::).
|
||
|
||
Usually, ‘dnl’ is immediately followed by an end of line or some
|
||
other whitespace. GNU ‘m4’ will produce a warning diagnostic if ‘dnl’
|
||
is followed by an open parenthesis. In this case, ‘dnl’ will collect
|
||
and process all arguments, looking for a matching close parenthesis.
|
||
All predictable side effects resulting from this collection will take
|
||
place. ‘dnl’ will return no output. The input following the matching
|
||
close parenthesis up to and including the next 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, a
|
||
warning 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
|
||
|
||
|
||
File: m4.info, Node: Changequote, Next: Changecom, Prev: Dnl, Up: Input Control
|
||
|
||
8.2 Changing the quote characters
|
||
=================================
|
||
|
||
The default quote delimiters can be changed with the builtin
|
||
‘changequote’:
|
||
|
||
-- Builtin: changequote ([START = ‘`’], [END = ‘'’])
|
||
This sets START as the new begin-quote delimiter and END as the new
|
||
end-quote delimiter. If both arguments are missing, the default
|
||
quotes (‘`’ and ‘'’) are used. If START is void, then quoting is
|
||
disabled. Otherwise, if END is missing or void, the default
|
||
end-quote delimiter (‘'’) is used. The quote delimiters can be of
|
||
any length.
|
||
|
||
The expansion of ‘changequote’ is void.
|
||
|
||
changequote(`[', `]')
|
||
⇒
|
||
define([foo], [Macro [foo].])
|
||
⇒
|
||
foo
|
||
⇒Macro foo.
|
||
|
||
The quotation strings can safely contain non-ASCII characters.
|
||
|
||
define(`a', `b')
|
||
⇒
|
||
«a»
|
||
⇒«b»
|
||
changequote(`«', `»')
|
||
⇒
|
||
«a»
|
||
⇒a
|
||
|
||
If no single character is appropriate, START and END can be of any
|
||
length. Other implementations cap the delimiter length to five
|
||
characters, but GNU has no inherent limit.
|
||
|
||
changequote(`[[[', `]]]')
|
||
⇒
|
||
define([[[foo]]], [[[Macro [[[[[foo]]]]].]]])
|
||
⇒
|
||
foo
|
||
⇒Macro [[foo]].
|
||
|
||
Calling ‘changequote’ with START as the empty string will effectively
|
||
disable the quoting mechanism, leaving no way to quote text. However,
|
||
using an empty string is not portable, as some other implementations of
|
||
‘m4’ revert to the default quoting, while others preserve the prior
|
||
non-empty delimiter. If START 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
|
||
other ‘m4’ implementations reuse START as the end-quote delimiter, while
|
||
others preserve the previous non-empty value. Omitting both arguments
|
||
restores the default begin-quote and end-quote delimiters; fortunately
|
||
this behavior is portable 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 unmatched
|
||
begin-quote, except using ‘changequote’ to change the current quotes.
|
||
|
||
If the quotes should be changed from, say, ‘[’ to ‘[[’, temporary
|
||
quote characters have to be defined. To achieve this, two calls of
|
||
‘changequote’ must be made, one for the temporary quotes and one for the
|
||
new quotes.
|
||
|
||
Macros are recognized in preference to the begin-quote string, so if
|
||
a prefix of START can be recognized as part of a potential macro name,
|
||
the quoting mechanism is effectively disabled. Unless you use
|
||
‘changeword’ (*note Changeword::), this means that START should not
|
||
begin with a letter, digit, or ‘_’ (underscore). However, even though
|
||
quoted strings are not recognized, the quote characters can still be
|
||
discerned in macro expansion and in trace output.
|
||
|
||
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. In
|
||
particular, if START is a single ‘(’, then argument collection is
|
||
effectively disabled. For portability with other implementations, 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 use it to
|
||
compute a quoted string containing the expansion of any quoted text, as
|
||
long as the expansion results in both balanced quotes and balanced
|
||
parentheses. The trick is realizing ‘expand’ uses ‘$1’ unquoted, to
|
||
trigger its expansion using the normal quoting characters, but uses
|
||
extra parentheses to group unquoted commas that occur in the expansion
|
||
without consuming whitespace following those commas. Then ‘_expand’
|
||
uses ‘changequote’ to convert the extra parentheses back into quoting
|
||
characters. Note that it takes two more ‘changequote’ invocations to
|
||
restore the original quotes. Contrast the behavior on whitespace when
|
||
using ‘$*’, via ‘quote’, 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 be recognized in
|
||
preference to a nested begin-quote. In particular, changing the quotes
|
||
to have the same string for START and END disables nesting of quotes.
|
||
When quote nesting is disabled, it is impossible to double-quote strings
|
||
across macro expansions, so using 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
|
||
|
||
|
||
File: m4.info, Node: Changecom, Next: Changeword, Prev: Changequote, Up: Input Control
|
||
|
||
8.3 Changing the comment delimiters
|
||
===================================
|
||
|
||
The default comment delimiters can be changed with the builtin macro
|
||
‘changecom’:
|
||
|
||
-- Builtin: changecom ([START], [END = ‘<NL>’])
|
||
This sets START as the new begin-comment delimiter and END as the
|
||
new end-comment delimiter. If both arguments are missing, or START
|
||
is void, then comments are disabled. Otherwise, if END is missing
|
||
or void, the default end-comment delimiter of newline 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
|
||
quoted strings. If you want the text inside a comment expanded, quote
|
||
the begin-comment delimiter.
|
||
|
||
Calling ‘changecom’ without any arguments, or with START as the empty
|
||
string, will effectively disable the commenting mechanism. To restore
|
||
the original comment start of ‘#’, you must explicitly ask for it. If
|
||
START is not empty, then an empty END will use the default end-comment
|
||
delimiter of newline, as otherwise, it would be impossible to end a
|
||
comment. However, this is not portable, as some other ‘m4’
|
||
implementations preserve the previous non-empty delimiters instead.
|
||
|
||
define(`comment', `COMMENT')
|
||
⇒
|
||
changecom
|
||
⇒
|
||
# Not a comment anymore
|
||
⇒# Not a COMMENT anymore
|
||
changecom(`#', `')
|
||
⇒
|
||
# comment again
|
||
⇒# comment again
|
||
|
||
The comment strings can safely contain non-ASCII characters.
|
||
|
||
define(`a', `b')
|
||
⇒
|
||
«a»
|
||
⇒«b»
|
||
changecom(`«', `»')
|
||
⇒
|
||
«a»
|
||
⇒«a»
|
||
|
||
If no single character is appropriate, START and END can be of any
|
||
length. Other implementations cap the delimiter length to five
|
||
characters, but GNU has no inherent limit.
|
||
|
||
Comments are recognized in preference to macros. However, this is
|
||
not compatible with other implementations, where macros and even quoting
|
||
takes precedence over comments, so it may change in a future release.
|
||
For portability, this means that START should not begin with a letter,
|
||
digit, or ‘_’ (underscore), and that neither the start-quote nor the
|
||
start-comment string should be a prefix of the other.
|
||
|
||
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. In
|
||
particular, if START is a single ‘(’, then argument collection is
|
||
effectively disabled. For portability with other implementations, 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
|
||
|
||
|
||
File: m4.info, Node: Changeword, Next: M4wrap, Prev: Changecom, Up: Input Control
|
||
|
||
8.4 Changing the lexical structure of words
|
||
===========================================
|
||
|
||
The macro ‘changeword’ and all associated functionality is
|
||
experimental. It is only available if the ‘--enable-changeword’
|
||
option was given to ‘configure’, at GNU ‘m4’ installation time.
|
||
The functionality will go away in the future, to be replaced by
|
||
other new features that are more efficient at providing the same
|
||
capabilities. _Do not rely on it_. Please direct your comments
|
||
about 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 be
|
||
REGEX. If REGEX is empty, use ‘[_a-zA-Z][_a-zA-Z0-9]*’. REGEX
|
||
must obey the constraint that every prefix of the desired final
|
||
pattern is also accepted by the regular expression. If REGEX
|
||
contains grouping parentheses, the macro invoked is the portion
|
||
that matched the first group, rather than the 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) if
|
||
you 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
|
||
generally make some of the builtins unavailable. You could use it to
|
||
prevent accidental 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, there is a
|
||
restriction on the regular expressions that may be passed to
|
||
‘changeword’. 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 expression
|
||
supplied contains any grouped subexpressions, then text outside the
|
||
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 every macro
|
||
invocation, so one can use ‘m4’ to preprocess plain text without losing
|
||
various words like ‘divert’.
|
||
|
||
In ‘m4’, macro substitution is based on text, while in TeX, it is
|
||
based on tokens. ‘changeword’ can throw this difference into relief.
|
||
For example, here is the same idea represented in TeX and ‘m4’. 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’ to print the
|
||
message ‘Hello’. The second line defines <@> to be usable instead of
|
||
<\> as an escape character. The third line defines <\> to be a normal
|
||
printing character, not an escape. The fourth line invokes the macro
|
||
‘a’. So, when TeX is run on 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 does lexical
|
||
analysis of macro definition when the macro is _defined_. ‘m4’ just
|
||
stores the text, postponing the lexical analysis until the macro is
|
||
_used_.
|
||
|
||
You should note that using ‘changeword’ will slow ‘m4’ down by a
|
||
factor of about seven, once it is changed to something other than the
|
||
default regular expression. You can invoke ‘changeword’ with the empty
|
||
string to restore the default word definition, and regain the parsing
|
||
speed.
|
||
|
||
|
||
File: m4.info, Node: M4wrap, Prev: 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 has
|
||
been seen. Text can be saved, to be read again by ‘m4’ when the normal
|
||
input has been exhausted. This feature is normally used to initiate
|
||
cleanup actions before normal exit, e.g., deleting temporary files.
|
||
|
||
To save input text, use the builtin ‘m4wrap’:
|
||
|
||
-- Builtin: m4wrap (STRING, ...)
|
||
Stores STRING in a safe place, to be reread when end of input is
|
||
reached. As a GNU extension, additional arguments are concatenated
|
||
with a space to the STRING.
|
||
|
||
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,
|
||
and not if ‘m4exit’ is used to exit ‘m4’.
|
||
|
||
It is safe to call ‘m4wrap’ from saved text, but then the order in
|
||
which the saved text is reread is undefined. If ‘m4wrap’ is not used
|
||
recursively, the saved pieces of text are reread in the opposite order
|
||
in which they were saved (LIFO—last in, first out). However, this
|
||
behavior is likely to change in a future release, to match POSIX, so you
|
||
should not depend on this order.
|
||
|
||
It is possible to emulate POSIX behavior even with older versions of
|
||
GNU M4 by including the file ‘m4-1.4.19/examples/wrapfifo.m4’ from the
|
||
distribution:
|
||
|
||
$ 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 to
|
||
the GNU M4 extension of ‘builtin’, by including the file
|
||
‘m4-1.4.19/examples/wraplifo.m4’ from the distribution. (Unfortunately,
|
||
both examples shown here share some subtle bugs. See if you can find
|
||
and correct them; or *note Answers: Improved m4wrap.).
|
||
|
||
$ 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 using
|
||
‘m4wrap’:
|
||
|
||
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 are concatenated
|
||
and rescanned as usual:
|
||
|
||
define(`aa', `AA
|
||
')
|
||
⇒
|
||
m4wrap(`a')m4wrap(`a')
|
||
⇒
|
||
^D
|
||
⇒AA
|
||
|
||
however, the transition between recursion levels behaves like an end of
|
||
file condition between two input files.
|
||
|
||
m4wrap(`m4wrap(`)')len(abc')
|
||
⇒
|
||
^D
|
||
error→m4:stdin:1: ERROR: end of file in argument list
|
||
|
||
|
||
File: m4.info, Node: File Inclusion, Next: Diversions, Prev: Input Control, Up: Top
|
||
|
||
9 File inclusion
|
||
****************
|
||
|
||
‘m4’ allows you to include named files at any point in the input.
|
||
|
||
* Menu:
|
||
|
||
* Include:: Including named files
|
||
* Search Path:: Searching for include files
|
||
|
||
|
||
File: m4.info, Node: Include, Next: Search Path, 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 by ‘m4’. When the
|
||
end of the file is reached, input is resumed from the previous
|
||
input file.
|
||
|
||
The expansion of ‘include’ and ‘sinclude’ is therefore the contents
|
||
of FILE.
|
||
|
||
If FILE does not exist, is a directory, or cannot otherwise be
|
||
read, the expansion is void, and ‘include’ will fail with an error
|
||
while ‘sinclude’ is silent. The empty string counts as a file that
|
||
does not exist.
|
||
|
||
The macros ‘include’ and ‘sinclude’ are recognized only with
|
||
parameters.
|
||
|
||
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 (*note Invoking m4: Preprocessor features.) pointing to the
|
||
‘m4-1.4.19/examples’ directory shipped as part of the GNU ‘m4’ package.
|
||
The file ‘m4-1.4.19/examples/incl.m4’ in the distribution contains the
|
||
lines:
|
||
|
||
$ cat examples/incl.m4
|
||
⇒Include file start
|
||
⇒foo
|
||
⇒Include file end
|
||
|
||
Normally file inclusion is used to insert the contents of a file into
|
||
the input stream. The contents of the file will be read by ‘m4’ 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 contents of the
|
||
file can be used to define macros that operate on entire files. Here is
|
||
an example, which defines ‘bar’ to expand to the contents of ‘incl.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 contain
|
||
quotes, commas, and parentheses, which can interfere with the way the
|
||
‘m4’ parser works. GNU ‘m4’ seamlessly concatenates the file contents
|
||
with the next character, even if the included file ended in the middle
|
||
of a comment, string, or macro call. These conditions are only treated
|
||
as end of file errors if specified as input files on the command line.
|
||
|
||
In GNU ‘m4’, an alternative method of reading files is using
|
||
‘undivert’ (*note Undivert::) on a named file.
|
||
|
||
|
||
File: m4.info, Node: Search Path, Prev: Include, Up: File Inclusion
|
||
|
||
9.2 Searching for include files
|
||
===============================
|
||
|
||
GNU ‘m4’ allows included files to be found in other directories than the
|
||
current working directory.
|
||
|
||
If the ‘--prepend-include’ or ‘-B’ command-line option was provided
|
||
(*note Invoking m4: Preprocessor features.), those directories are
|
||
searched first, in reverse order that those options were listed on the
|
||
command line. Then ‘m4’ looks in the current working directory. Next
|
||
comes the directories specified with the ‘--include’ or ‘-I’ option, in
|
||
the order found on the command line. Finally, if the ‘M4PATH’
|
||
environment variable is set, it is expected to contain a colon-separated
|
||
list of directories, which will be searched in order.
|
||
|
||
If the automatic search for include-files causes trouble, the ‘p’
|
||
debug flag (*note Debug Levels::) can help isolate the problem.
|
||
|
||
|
||
File: m4.info, Node: Diversions, Next: Text handling, Prev: File Inclusion, Up: Top
|
||
|
||
10 Diverting and undiverting output
|
||
***********************************
|
||
|
||
Diversions are a way of temporarily saving output. The output of ‘m4’
|
||
can at any time be diverted to a temporary file, and be reinserted into
|
||
the output stream, “undiverted”, again at a later time.
|
||
|
||
Numbered diversions are counted from 0 upwards, diversion number 0
|
||
being the normal output stream. GNU ‘m4’ tries to keep diversions in
|
||
memory. However, there is a limit 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 biggest diversion still in memory, freeing this memory for other
|
||
diversions. When creating the temporary file, ‘m4’ honors the value of
|
||
the environment variable ‘TMPDIR’, and falls back to ‘/tmp’. Thus, the
|
||
amount of available disk space provides the only real limit on the
|
||
number and aggregate size of diversions.
|
||
|
||
Diversions make it possible to generate output in a different order
|
||
than the input was read. It is possible to implement topological
|
||
sorting dependencies. For example, GNU Autoconf makes use of diversions
|
||
under the hood to ensure that the expansion of a prerequisite macro
|
||
appears in the output prior to the expansion of a dependent macro,
|
||
regardless of which order the two macros were invoked in the user’s
|
||
input file.
|
||
|
||
* Menu:
|
||
|
||
* Divert:: Diverting output
|
||
* Undivert:: Undiverting output
|
||
* Divnum:: Diversion numbers
|
||
* Cleardivert:: Discarding diverted text
|
||
|
||
|
||
File: m4.info, Node: Divert, Next: Undivert, Up: Diversions
|
||
|
||
10.1 Diverting output
|
||
=====================
|
||
|
||
Output is diverted using ‘divert’:
|
||
|
||
-- Builtin: divert ([NUMBER = ‘0’])
|
||
The current diversion is changed to NUMBER. If NUMBER is left out
|
||
or empty, it is assumed to be zero. If NUMBER cannot be parsed,
|
||
the diversion is unchanged.
|
||
|
||
The expansion of ‘divert’ is void.
|
||
|
||
When all the ‘m4’ input will have been processed, all existing
|
||
diversions 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 overwrite the
|
||
previous diverted text, but append to it. Diversions are printed after
|
||
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 of unwanted output is the trailing newlines after macro
|
||
definitions. Here is 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 a
|
||
GNU extension, diversion numbers can be as large as positive integers
|
||
will allow, rather than treating a multi-digit diversion number as 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 macro
|
||
without arguments. When processing plain text, the word might appear in
|
||
normal text and be unintentionally swallowed as a macro invocation. One
|
||
way to avoid this is to use the ‘-P’ option to rename all builtins
|
||
(*note Invoking m4: Operation modes.). Another is to write a 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.
|
||
|
||
|
||
File: m4.info, Node: Undivert, Next: Divnum, Prev: Divert, Up: Diversions
|
||
|
||
10.2 Undiverting output
|
||
=======================
|
||
|
||
Diverted text can be undiverted explicitly using the builtin ‘undivert’:
|
||
|
||
-- Builtin: undivert ([DIVERSIONS...])
|
||
Undiverts the numeric DIVERSIONS given by the arguments, in the
|
||
order given. If no arguments are supplied, all diversions are
|
||
undiverted, in numerical order.
|
||
|
||
As a GNU extension, DIVERSIONS may contain non-numeric strings,
|
||
which are treated as the names of files to copy into the output
|
||
without 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 newline
|
||
following ‘undivert’, the other from the newline that followed the
|
||
‘divert’! 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 therefore not an
|
||
error to undivert into a diversion. Undiverting the empty string is the
|
||
same as specifying diversion 0; in either case nothing happens since 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 get rearranged among the other diversions.
|
||
|
||
divert(`1')one
|
||
divert(`2')two
|
||
divert(`3')three
|
||
divert(`2')undivert`'dnl
|
||
divert`'undivert`'dnl
|
||
⇒two
|
||
⇒one
|
||
⇒three
|
||
|
||
GNU ‘m4’ allows named files to be undiverted. Given a non-numeric
|
||
argument, the contents of the file named will be copied, uninterpreted,
|
||
to the current output. This complements the builtin ‘include’ (*note
|
||
Include::). To illustrate the difference, assume the 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 is
|
||
issued, and the expansion is void. It is possible to intermix files and
|
||
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
|
||
|
||
|
||
File: m4.info, Node: Divnum, Next: Cleardivert, Prev: Undivert, Up: Diversions
|
||
|
||
10.3 Diversion numbers
|
||
======================
|
||
|
||
The current diversion is tracked by the builtin ‘divnum’:
|
||
|
||
-- 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
|
||
|
||
|
||
File: m4.info, Node: Cleardivert, Prev: Divnum, Up: Diversions
|
||
|
||
10.4 Discarding diverted text
|
||
=============================
|
||
|
||
Often it is not known, when output is diverted, whether the diverted
|
||
text is actually needed. Since all non-empty diversion are brought back
|
||
on the main output stream when the end of input is seen, a method of
|
||
discarding a diversion is needed. If all diversions should be
|
||
discarded, the easiest is to end the input to ‘m4’ 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 the
|
||
diversions, given by the arguments. (This macro has a nasty bug! You
|
||
should try to see if you can find it and correct it; or *note Answers:
|
||
Improved cleardivert.).
|
||
|
||
|
||
File: m4.info, Node: Text handling, Next: Arithmetic, Prev: Diversions, Up: Top
|
||
|
||
11 Macros for text handling
|
||
***************************
|
||
|
||
There are a number of builtins in ‘m4’ for manipulating text in various
|
||
ways, extracting substrings, searching, substituting, and so on.
|
||
|
||
* Menu:
|
||
|
||
* Len:: Calculating length of strings
|
||
* Index macro:: Searching for substrings
|
||
* Regexp:: Searching for regular expressions
|
||
* Substr:: Extracting substrings
|
||
* Translit:: Translating characters
|
||
* Patsubst:: Substituting text by regular expression
|
||
* Format:: Formatting strings (printf-like)
|
||
|
||
|
||
File: m4.info, Node: Len, Next: Index macro, Up: Text handling
|
||
|
||
11.1 Calculating length of strings
|
||
==================================
|
||
|
||
The length of a string can be calculated by ‘len’:
|
||
|
||
-- 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
|
||
|
||
|
||
File: m4.info, Node: Index macro, Next: Regexp, Prev: Len, Up: Text handling
|
||
|
||
11.2 Searching for substrings
|
||
=============================
|
||
|
||
Searching for substrings is done with ‘index’:
|
||
|
||
-- Builtin: index (STRING, SUBSTRING)
|
||
Expands to the index of the first occurrence of SUBSTRING in
|
||
STRING. The first character in STRING has index 0. If SUBSTRING
|
||
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 empty SUBSTRING.
|
||
|
||
index(`abc')
|
||
error→m4:stdin:1: Warning: too few arguments to builtin `index'
|
||
⇒0
|
||
index(`abc', `')
|
||
⇒0
|
||
index(`abc', `b')
|
||
⇒1
|
||
|
||
|
||
File: m4.info, Node: Regexp, Next: Substr, Prev: Index macro, Up: Text handling
|
||
|
||
11.3 Searching for regular expressions
|
||
======================================
|
||
|
||
Searching for regular expressions is done with the builtin ‘regexp’:
|
||
|
||
-- Builtin: regexp (STRING, REGEXP, [REPLACEMENT])
|
||
Searches for REGEXP in STRING. The syntax for regular expressions
|
||
is the same as in GNU Emacs, which is similar to BRE, Basic Regular
|
||
Expressions in POSIX. *Note Syntax of Regular Expressions:
|
||
(emacs)Regexps. Support for ERE, Extended Regular Expressions is
|
||
not available, but will be added in GNU M4 2.0.
|
||
|
||
If REPLACEMENT is omitted, ‘regexp’ expands to the index of the
|
||
first match of REGEXP in STRING. If REGEXP does not match anywhere
|
||
in STRING, it expands to -1.
|
||
|
||
If REPLACEMENT is supplied, and there was a match, ‘regexp’ changes
|
||
the expansion to this argument, with ‘\N’ substituted by the text
|
||
matched by the Nth parenthesized sub-expression of REGEXP, up to
|
||
nine sub-expressions. The escape ‘\&’ is replaced by the text of
|
||
the entire regular expression matched. For all other characters,
|
||
‘\’ treats the next character literally. A warning is issued if
|
||
there were fewer sub-expressions than the ‘\N’ requested, or if
|
||
there is a trailing ‘\’. If there was 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 empty REGEXP argument.
|
||
|
||
regexp(`abc')
|
||
error→m4:stdin:1: Warning: too few arguments to builtin `regexp'
|
||
⇒0
|
||
regexp(`abc', `')
|
||
⇒0
|
||
regexp(`abc', `', `\\def')
|
||
⇒\def
|
||
|
||
|
||
File: m4.info, Node: Substr, Next: Translit, Prev: Regexp, Up: Text handling
|
||
|
||
11.4 Extracting substrings
|
||
==========================
|
||
|
||
Substrings are extracted with ‘substr’:
|
||
|
||
-- Builtin: substr (STRING, FROM, [LENGTH])
|
||
Expands to the substring of STRING, which starts at index FROM, and
|
||
extends for LENGTH characters, or to the end of STRING, if LENGTH
|
||
is omitted. The starting index of a string is always 0. The
|
||
expansion is empty if there is an error parsing FROM or LENGTH, if
|
||
FROM is beyond the end of STRING, or if LENGTH 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
|
||
|
||
|
||
File: m4.info, Node: Translit, Next: Patsubst, Prev: Substr, Up: Text handling
|
||
|
||
11.5 Translating characters
|
||
===========================
|
||
|
||
Character translation is done with ‘translit’:
|
||
|
||
-- Builtin: translit (STRING, CHARS, [REPLACEMENT])
|
||
Expands to STRING, with each character that occurs in CHARS
|
||
translated into the character from REPLACEMENT with the same index.
|
||
|
||
If REPLACEMENT is shorter than CHARS, the excess characters of
|
||
CHARS are deleted from the expansion; if CHARS is shorter, the
|
||
excess characters in REPLACEMENT are silently ignored. If
|
||
REPLACEMENT is omitted, all characters in STRING that are present
|
||
in CHARS are deleted from the expansion. If a character appears
|
||
more than once in CHARS, only the first instance is used in making
|
||
the translation. Only a single translation pass is made, even if
|
||
characters in REPLACEMENT also appear in CHARS.
|
||
|
||
As a GNU extension, both CHARS and REPLACEMENT can contain
|
||
character-ranges, e.g., ‘a-z’ (meaning all lowercase letters) or
|
||
‘0-9’ (meaning all digits). To include a dash ‘-’ in CHARS or
|
||
REPLACEMENT, place it first or last in the entire string, or as the
|
||
last character of a range. Back-to-back ranges can share a common
|
||
endpoint. It is not an error for the last character in the range
|
||
to be ‘larger’ than the first. In that case, the range runs
|
||
backwards, i.e., ‘9-0’ means the string ‘9876543210’. The
|
||
expansion of a range is dependent on the underlying encoding of
|
||
characters, 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 uppercase
|
||
letters, 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 not
|
||
portable to EBCDIC or other encodings. The fourth example shows a range
|
||
ending in ‘-’, as well as back-to-back ranges. The final example shows
|
||
that ‘a’ is mapped to ‘b’, not ‘c’; the resulting ‘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
|
||
|
||
|
||
File: m4.info, Node: Patsubst, Next: Format, Prev: 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 substitutes REPLACEMENT
|
||
for each match. The syntax for regular expressions is the same as
|
||
in GNU Emacs (*note Regexp::).
|
||
|
||
The parts of STRING that are not covered by any match of REGEXP are
|
||
copied to the expansion. Whenever a match is found, the search
|
||
proceeds from the end of the match, so a character from STRING will
|
||
never be substituted twice. If REGEXP matches a string 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 into the
|
||
expansion, with ‘\N’ substituted by the text matched by the Nth
|
||
parenthesized sub-expression of PATSUBST, for up to nine
|
||
sub-expressions. The escape ‘\&’ is replaced by the text of the
|
||
entire regular expression matched. For all other characters, ‘\’
|
||
treats the next character literally. A warning is issued if there
|
||
were fewer sub-expressions than the ‘\N’ requested, or if there is
|
||
a trailing ‘\’.
|
||
|
||
The REPLACEMENT argument can be omitted, in which case the text
|
||
matched by REGEXP 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
|
||
individual words or whole sentences, by substituting calls of the macros
|
||
‘upcase’ and ‘downcase’ into the strings.
|
||
|
||
-- Composite: upcase (TEXT)
|
||
-- Composite: downcase (TEXT)
|
||
-- Composite: capitalize (TEXT)
|
||
Expand to TEXT, but with capitalization changed: ‘upcase’ changes
|
||
all letters to upper case, ‘downcase’ changes all letters to lower
|
||
case, and ‘capitalize’ changes the first character of each word to
|
||
upper case and the remaining characters to lower case.
|
||
|
||
First, an example of their usage, using implementations distributed
|
||
in ‘m4-1.4.19/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 ‘_capitalize’
|
||
which puts only its first word in mixed case. Then ‘capitalize’ merely
|
||
parses out the words, and replaces them with an invocation of
|
||
‘_capitalize’. (As presented here, the ‘capitalize’ macro has some
|
||
subtle flaws. You should try to see if you can find and correct them;
|
||
or *note Answers: Improved capitalize.).
|
||
|
||
$ 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 as soon
|
||
as there is a match, ‘patsubst’ replaces each _occurrence_ 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 empty REGEXP argument.
|
||
|
||
patsubst(`abc')
|
||
error→m4:stdin:1: Warning: too few arguments to builtin `patsubst'
|
||
⇒abc
|
||
patsubst(`abc', `')
|
||
⇒abc
|
||
patsubst(`abc', `', `\\-')
|
||
⇒\-a\-b\-c\-
|
||
|
||
|
||
File: m4.info, Node: Format, Prev: Patsubst, Up: Text handling
|
||
|
||
11.7 Formatting strings (printf-like)
|
||
=====================================
|
||
|
||
Formatted output can be made with ‘format’:
|
||
|
||
-- Builtin: format (FORMAT-STRING, ...)
|
||
Works much like the C function ‘printf’. The first argument
|
||
FORMAT-STRING can contain ‘%’ specifications which are satisfied by
|
||
additional arguments, and the expansion of ‘format’ is the
|
||
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 (*note Forloop::), this
|
||
example shows how ‘format’ 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 ‘'’.
|
||
For integer specifiers, the width modifiers ‘hh’, ‘h’, and ‘l’ are
|
||
recognized, and for floating point specifiers, the width modifier ‘l’ is
|
||
recognized. Items not yet supported include positional arguments, the
|
||
‘n’, ‘p’, ‘S’, and ‘C’ specifiers, the ‘z’, ‘t’, ‘j’, ‘L’ and ‘ll’
|
||
modifiers, and any platform extensions available in the native ‘printf’.
|
||
For more details on the functioning of ‘printf’, see the C Library
|
||
Manual, or the POSIX specification (for example, ‘%a’ is supported even
|
||
on platforms that haven’t yet implemented C99 hexadecimal floating point
|
||
output natively).
|
||
|
||
Unrecognized specifiers result in a warning. It is anticipated that
|
||
a future release of GNU ‘m4’ will support more specifiers, and give
|
||
better warnings when various problems such as overflow are encountered.
|
||
Likewise, escape sequences are not yet recognized.
|
||
|
||
format(`%p', `0')
|
||
error→m4:stdin:1: Warning: unrecognized specifier in `%p'
|
||
⇒
|
||
|
||
|
||
File: m4.info, Node: Arithmetic, Next: Shell commands, Prev: Text handling, Up: Top
|
||
|
||
12 Macros for doing arithmetic
|
||
******************************
|
||
|
||
Integer arithmetic is included in ‘m4’, with a C-like syntax. As
|
||
convenient shorthands, there are builtins for simple increment and
|
||
decrement operations.
|
||
|
||
* Menu:
|
||
|
||
* Incr:: Decrement and increment operators
|
||
* Eval:: Evaluating integer expressions
|
||
|
||
|
||
File: m4.info, Node: Incr, Next: Eval, Up: Arithmetic
|
||
|
||
12.1 Decrement and increment operators
|
||
======================================
|
||
|
||
Increment and decrement of integers are supported using the builtins
|
||
‘incr’ and ‘decr’:
|
||
|
||
-- Builtin: incr (NUMBER)
|
||
-- Builtin: decr (NUMBER)
|
||
Expand to the numerical value of NUMBER, incremented or
|
||
decremented, respectively, by one. Except for the empty string,
|
||
the expansion is empty if NUMBER could not be parsed.
|
||
|
||
The macros ‘incr’ and ‘decr’ are recognized only with parameters.
|
||
|
||
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
|
||
|
||
|
||
File: m4.info, Node: Eval, Prev: Incr, Up: Arithmetic
|
||
|
||
12.2 Evaluating integer expressions
|
||
===================================
|
||
|
||
Integer expressions are evaluated with ‘eval’:
|
||
|
||
-- Builtin: eval (EXPRESSION, [RADIX = ‘10’], [WIDTH])
|
||
Expands to the value of EXPRESSION. The expansion is empty if a
|
||
problem is encountered while parsing the arguments. If specified,
|
||
RADIX and WIDTH control the format of the output.
|
||
|
||
Calculations are done with 32-bit signed numbers. Overflow
|
||
silently results in wraparound. A warning is issued if division by
|
||
zero is attempted, or if EXPRESSION could not be parsed.
|
||
|
||
Expressions can contain the following operators, listed in order of
|
||
decreasing 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. C
|
||
operators that perform variable assignment, such as ‘+=’ or ‘--’, are
|
||
not implemented, since ‘eval’ only operates on constants, not variables.
|
||
Attempting to use them results in an error. However, since traditional
|
||
implementations treated ‘=’ as an undocumented alias for ‘==’ as opposed
|
||
to an assignment operator, this usage is supported as a special case.
|
||
Be aware that a future version of GNU M4 may support assignment
|
||
semantics as an extension 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 an alternate
|
||
operator for the exponentiation, although POSIX requires the C behavior
|
||
of bitwise exclusive-or. The precedence of the negation operators, ‘~’
|
||
and ‘!’, was traditionally lower than equality. The unary operators
|
||
could not be used reliably more than once on the same term without
|
||
intervening parentheses. The traditional precedence of the equality
|
||
operators ‘==’ and ‘!=’ was identical instead of lower than the
|
||
relational operators such as ‘<’, even through GNU M4 1.4.8. Starting
|
||
with version 1.4.9, GNU M4 correctly follows POSIX precedence rules. M4
|
||
scripts designed to be portable between releases must be aware that
|
||
parentheses may be required to enforce C precedence rules. Likewise,
|
||
division by zero, even in the unused branch of a short-circuiting
|
||
operator, is not always well-defined in other implementations.
|
||
|
||
Following are some examples where the current version of M4 follows C
|
||
precedence rules, but where older versions and some other
|
||
implementations of ‘m4’ require explicit parentheses to get the correct
|
||
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 integral
|
||
exponentiation. The operator is right-associative, and if evaluated,
|
||
the exponent must be non-negative, and at least one of the arguments
|
||
must 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), numbers without a
|
||
special prefix are decimal. A simple ‘0’ prefix introduces 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 of the 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’ ... up to ‘z’. Lower and
|
||
upper case letters can be used interchangeably in numbers prefixes and
|
||
as number digits.
|
||
|
||
Parentheses may be used to group subexpressions whenever needed. For
|
||
the relational operators, a true relation returns ‘1’, and a false
|
||
relation 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 macro names, even
|
||
if they expand to a valid expression (or part of a valid expression).
|
||
Therefore all macros must be expanded before they are passed to ‘eval’.
|
||
|
||
Some calculations are not portable to other implementations, since
|
||
they have undefined semantics in C, but GNU ‘m4’ has well-defined
|
||
behavior on overflow. When shifting, an out-of-range shift amount is
|
||
implicitly brought into the range of 32-bit signed integers using 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 the
|
||
expansion. The default radix is 10; this is also the case if RADIX is
|
||
the empty string. A warning results if the radix is outside the range
|
||
of 1 through 36, inclusive. The result of ‘eval’ is always taken to be
|
||
signed. No radix prefix is output, and for radices greater than 10, the
|
||
digits are lower case. The WIDTH argument specifies the minimum output
|
||
width, excluding any negative sign. The result is zero-padded to extend
|
||
the expansion to the requested width. A warning results if the width is
|
||
negative. If RADIX or WIDTH is out of bounds, the expansion of ‘eval’
|
||
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
|
||
|
||
|
||
File: m4.info, Node: Shell commands, Next: Miscellaneous, Prev: Arithmetic, Up: Top
|
||
|
||
13 Macros for running shell commands
|
||
************************************
|
||
|
||
There are a few builtin macros in ‘m4’ that allow you to run shell
|
||
commands from within ‘m4’.
|
||
|
||
Note that the definition of a valid shell command is system
|
||
dependent. On UNIX systems, this is the typical ‘/bin/sh’. But on
|
||
other systems, such as native Windows, the shell has a different syntax
|
||
of commands that it understands. Some examples in this chapter assume
|
||
‘/bin/sh’, and also demonstrate how to quit early with a known exit
|
||
value if this is not the case.
|
||
|
||
* Menu:
|
||
|
||
* Platform macros:: Determining the platform
|
||
* Syscmd:: Executing simple commands
|
||
* Esyscmd:: Reading the output of commands
|
||
* Sysval:: Exit status
|
||
* Mkstemp:: Making temporary files
|
||
|
||
|
||
File: m4.info, Node: Platform macros, Next: Syscmd, Up: Shell commands
|
||
|
||
13.1 Determining the platform
|
||
=============================
|
||
|
||
Sometimes it is desirable for an input file to know which platform ‘m4’
|
||
is running on. GNU ‘m4’ provides several macros that are predefined to
|
||
expand to the empty string; checking for their 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
|
||
the environment of ‘m4’. If defined, each macro expands to the
|
||
empty string. For now, these macros silently ignore all arguments,
|
||
but in a future release of M4, they might warn if arguments are
|
||
present.
|
||
|
||
When GNU extensions are in effect (that is, when you did not use the
|
||
‘-G’ option, *note Invoking m4: Limits control.), GNU ‘m4’ will define
|
||
the macro ‘__gnu__’ to expand 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, or
|
||
‘unix’ when the ‘-G’ option is specified.
|
||
|
||
On native Windows systems, GNU ‘m4’ will define ‘__windows__’ by
|
||
default, or ‘windows’ when the ‘-G’ option is specified.
|
||
|
||
On OS/2 systems, GNU ‘m4’ will define ‘__os2__’ by default, or ‘os2’
|
||
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
|
||
|
||
|
||
File: m4.info, Node: Syscmd, Next: Esyscmd, Prev: 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 from
|
||
SHELL-COMMAND! Output or error messages from SHELL-COMMAND are not
|
||
read by ‘m4’. *Note Esyscmd::, if you need to process the command
|
||
output.
|
||
|
||
Prior to executing the command, ‘m4’ flushes its buffers. The
|
||
default standard input, output and error of SHELL-COMMAND are the
|
||
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 of ‘sh’
|
||
specified by ‘command -p getconf PATH’, if your system supports
|
||
that). If you prefer a different shell, the ‘configure’ script can
|
||
be given the option ‘--with-syscmd-shell=LOCATION’ to set the
|
||
location of an alternative shell at GNU ‘m4’ installation; the
|
||
alternative 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 of the
|
||
command, as well as using the newline that appeared after the macro.
|
||
|
||
The following is an example of SHELL-COMMAND using the same standard
|
||
input as ‘m4’:
|
||
|
||
$ echo "m4wrap(\`syscmd(\`cat')')" | m4
|
||
⇒
|
||
|
||
It tells ‘m4’ to read all of its input before executing the wrapped
|
||
text, then hand a valid (albeit emptied) pipe as standard input for the
|
||
‘cat’ subcommand. Therefore, you should be careful when using standard
|
||
input (either by specifying no files, or by passing ‘-’ as a file name
|
||
on the command line, *note Invoking m4: Command line files.), and also
|
||
invoking subcommands via ‘syscmd’ or ‘esyscmd’ that consume data from
|
||
standard input. When standard input is a seekable file, the subprocess
|
||
will pick up with the next character not yet processed by ‘m4’; when it
|
||
is a pipe or other non-seekable file, there is no guarantee how much
|
||
data will already be buffered by ‘m4’ and thus unavailable to the child.
|
||
|
||
|
||
File: m4.info, Node: Esyscmd, Next: Sysval, Prev: Syscmd, Up: Shell commands
|
||
|
||
13.3 Reading the output of commands
|
||
===================================
|
||
|
||
If you want ‘m4’ to read the output of a shell command, use ‘esyscmd’:
|
||
|
||
-- Builtin: esyscmd (SHELL-COMMAND)
|
||
Expands to the standard output of the shell command SHELL-COMMAND.
|
||
|
||
Prior to executing the command, ‘m4’ flushes its buffers. The
|
||
default standard input and standard error of SHELL-COMMAND are the
|
||
same as those of ‘m4’. The error output of SHELL-COMMAND is not a
|
||
part of the expansion: it will appear along with the error output
|
||
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 of ‘sh’
|
||
specified by ‘command -p getconf PATH’, if your system supports
|
||
that). If you prefer a different shell, the ‘configure’ script can
|
||
be given the option ‘--with-syscmd-shell=LOCATION’ to set the
|
||
location of an alternative shell at GNU ‘m4’ installation; the
|
||
alternative 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 of the
|
||
command, as well as using the newline that appeared after the macro.
|
||
|
||
Just as with ‘syscmd’, care must be exercised when sharing standard
|
||
input between ‘m4’ and the child process of ‘esyscmd’.
|
||
|
||
|
||
File: m4.info, Node: Sysval, Next: Mkstemp, Prev: 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 with
|
||
‘syscmd’ or ‘esyscmd’. Expands to 0 if no command has been run
|
||
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 the command,
|
||
for example, if the system-imposed argument length is exceeded, or if
|
||
there were not enough resources to fork. It is not possible to
|
||
distinguish between failed execution and successful execution that had
|
||
an exit status of 127, unless there was output from the child process.
|
||
|
||
On UNIX platforms, where it is possible to detect when command
|
||
execution is terminated by a signal, rather than a normal exit, the
|
||
result is the signal 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
|
||
changequote(`[', `]')
|
||
⇒
|
||
syscmd([/bin/sh -c 'kill -9 $$'; st=$?; test $st = 137 || test $st = 265])
|
||
⇒
|
||
ifelse(sysval, [0], , [errprint([ skipping: shell does not send signal 9
|
||
])m4exit([77])])dnl
|
||
syscmd([kill -9 $$])
|
||
⇒
|
||
sysval
|
||
⇒2304
|
||
syscmd()
|
||
⇒
|
||
sysval
|
||
⇒0
|
||
esyscmd([kill -9 $$])
|
||
⇒
|
||
sysval
|
||
⇒2304
|
||
|
||
|
||
File: m4.info, Node: Mkstemp, Prev: Sysval, Up: Shell commands
|
||
|
||
13.5 Making temporary files
|
||
===========================
|
||
|
||
Commands specified to ‘syscmd’ or ‘esyscmd’ might need a temporary file,
|
||
for output or for some other purpose. There is a builtin 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
|
||
string TEMPLATE, which should end with the string ‘XXXXXX’. The
|
||
six ‘X’ characters are then replaced with random characters
|
||
matching the regular expression ‘[a-zA-Z0-9._-]’, in order to make
|
||
the file name unique. If fewer than six ‘X’ characters are found
|
||
at the end of ‘template’, the result will be longer than the
|
||
template. The created file will have access permissions as if by
|
||
‘chmod =rw,go=’, meaning that the current umask of the ‘m4’ process
|
||
is taken into account, and at most only the current user can read
|
||
and write the file.
|
||
|
||
The traditional behavior, standardized by POSIX, is that ‘maketemp’
|
||
merely replaces the trailing ‘X’ with the process id, without
|
||
creating a file or quoting the expansion, and without ensuring that
|
||
the resulting string is a unique file name. In part, this means
|
||
that using the same TEMPLATE twice in the same input file will
|
||
result in the same expansion. This behavior is a security hole, as
|
||
it is very easy for another process to guess the name that will be
|
||
generated, and thus interfere with a subsequent use of ‘syscmd’
|
||
trying to manipulate that file name. Hence, POSIX has recommended
|
||
that all new implementations of ‘m4’ provide the secure ‘mkstemp’
|
||
builtin, and that users of ‘m4’ check for its existence.
|
||
|
||
The expansion is void and an error issued if a temporary file could
|
||
not be created.
|
||
|
||
The macros ‘mkstemp’ and ‘maketemp’ are recognized only with
|
||
parameters.
|
||
|
||
If you try this next example, you will most likely get different
|
||
output for the two file names, since the replacement characters are
|
||
randomly chosen:
|
||
|
||
$ 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’,
|
||
*note Invoking m4: Limits control.), the GNU version of ‘maketemp’ is
|
||
secure. This means that using the same template to multiple calls will
|
||
generate multiple files. However, we recommend that you use the new
|
||
‘mkstemp’ macro, introduced in GNU M4 1.4.8, which is secure even in
|
||
traditional mode. Also, as of M4 1.4.11, the secure implementation
|
||
quotes the resulting file name, so that you are guaranteed to know what
|
||
file was created even if the random file name happens to match an
|
||
existing macro. Notice that this example is careful to use ‘defn’ to
|
||
avoid unintended expansion of ‘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
|
||
|
||
|
||
File: m4.info, Node: Miscellaneous, Next: Frozen files, Prev: Shell commands, Up: Top
|
||
|
||
14 Miscellaneous builtin macros
|
||
*******************************
|
||
|
||
This chapter describes various builtins, that do not really belong in
|
||
any of the previous chapters.
|
||
|
||
* Menu:
|
||
|
||
* Errprint:: Printing error messages
|
||
* Location:: Printing current location
|
||
* M4exit:: Exiting from ‘m4’
|
||
|
||
|
||
File: m4.info, Node: Errprint, Next: Location, Up: Miscellaneous
|
||
|
||
14.1 Printing error messages
|
||
============================
|
||
|
||
You can print error messages using ‘errprint’:
|
||
|
||
-- 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 (*note Invoking m4: Debugging options.).
|
||
|
||
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 be
|
||
supplied as part of the argument, as in the example. Unfortunately, the
|
||
exact output of ‘errprint’ is not very portable to other ‘m4’
|
||
implementations: POSIX requires that all arguments be printed, but some
|
||
implementations of ‘m4’ only print the first. Furthermore, some BSD
|
||
implementations always append a newline for each ‘errprint’ call,
|
||
regardless of whether the last argument already had one, and POSIX is
|
||
silent on whether this is acceptable.
|
||
|
||
|
||
File: m4.info, Node: Location, Next: M4exit, Prev: Errprint, Up: Miscellaneous
|
||
|
||
14.2 Printing current location
|
||
==============================
|
||
|
||
To make it possible to specify the location of an error, three utility
|
||
builtins exist:
|
||
|
||
-- Builtin: __file__
|
||
-- Builtin: __line__
|
||
-- Builtin: __program__
|
||
Expand to the quoted name of the current input file, the current
|
||
input line number in that file, and the quoted name of the current
|
||
invocation of ‘m4’.
|
||
|
||
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 or ‘M4PATH’ environment variable, that is reflected in
|
||
the file name. The syncline option (‘-s’, *note Invoking m4:
|
||
Preprocessor features.), and the ‘f’ and ‘l’ flags of ‘debugmode’ (*note
|
||
Debug Levels::), also use this notion of current file and line.
|
||
Redefining the three location macros has no effect on syncline, debug,
|
||
warning, or error message output.
|
||
|
||
This example reuses the file ‘incl.m4’ mentioned earlier (*note
|
||
Include::):
|
||
|
||
$ 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
|
||
expansion text corresponds to the location in the file where the
|
||
expansion was triggered, regardless of how many newline characters the
|
||
expansion text contains. As of GNU M4 1.4.8, the location of text
|
||
wrapped with ‘m4wrap’ (*note M4wrap::) is the point at which the
|
||
‘m4wrap’ was invoked. Previous versions, however, behaved as though
|
||
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 shell terminology. If
|
||
you invoke ‘m4’ through an absolute path or a link with a different
|
||
spelling, rather than by relying on a ‘PATH’ search for plain ‘m4’, it
|
||
will affect how ‘__program__’ expands. The intent is that you can use
|
||
it to produce error messages with the same formatting that ‘m4’ produces
|
||
internally. It can also be used within ‘syscmd’ (*note Syscmd::) to
|
||
pick the same version of ‘m4’ that is currently running, rather than
|
||
whatever version of ‘m4’ happens to be first in ‘PATH’. It was first
|
||
introduced in GNU M4 1.4.6.
|
||
|
||
|
||
File: m4.info, Node: M4exit, Prev: Location, Up: Miscellaneous
|
||
|
||
14.3 Exiting from ‘m4’
|
||
======================
|
||
|
||
If you need to exit from ‘m4’ before the entire input has been read, you
|
||
can use ‘m4exit’:
|
||
|
||
-- Builtin: m4exit ([CODE = ‘0’])
|
||
Causes ‘m4’ to exit, with exit status CODE. If CODE is left out,
|
||
the exit status is zero. If CODE cannot be parsed, or is outside
|
||
the range of 0 to 255, the exit status is one. No further input 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. Prefix
|
||
MESSAGE with details about where the error occurred, and print the
|
||
resulting 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 macro
|
||
is only intended for error exits, since the normal exit procedures are
|
||
not followed, i.e., diverted text is not undiverted, and saved text
|
||
(*note M4wrap::) is not reread. (This macro could be made more robust
|
||
to earlier versions of ‘m4’. You should try to see if you can find
|
||
weaknesses and correct them; or *note Answers: Improved fatal_error.).
|
||
|
||
Note that it is still possible for the exit status to be different
|
||
than what was requested by ‘m4exit’. If ‘m4’ detects some other error,
|
||
such as a write error on standard output, the exit status will be
|
||
non-zero even if ‘m4exit’ requested zero.
|
||
|
||
If standard input is seekable, then the file will be positioned at
|
||
the next unread character. If it is a pipe or other non-seekable file,
|
||
then there are no guarantees how much data ‘m4’ might have read into
|
||
buffers, and thus discarded.
|
||
|
||
|
||
File: m4.info, Node: Frozen files, Next: Compatibility, Prev: Miscellaneous, Up: Top
|
||
|
||
15 Fast loading of frozen state
|
||
*******************************
|
||
|
||
Some bigger ‘m4’ applications may be built over a common base containing
|
||
hundreds of definitions and other costly initializations. Usually, the
|
||
common base is kept in one or more declarative files, which files are
|
||
listed on each ‘m4’ invocation prior to the user’s input file, or else
|
||
each input file uses ‘include’.
|
||
|
||
Reading the common base of a big application, over and over again,
|
||
may be time consuming. GNU ‘m4’ offers some machinery to speed up the
|
||
start of an application using lengthy common bases.
|
||
|
||
* Menu:
|
||
|
||
* Using frozen files:: Using frozen files
|
||
* Frozen file format:: Frozen file format
|
||
|
||
|
||
File: m4.info, Node: Using frozen files, Next: Frozen file format, Up: Frozen files
|
||
|
||
15.1 Using frozen files
|
||
=======================
|
||
|
||
Suppose a user has a library of ‘m4’ initializations in ‘base.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.m4’
|
||
every 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 ‘-F’ option,
|
||
only reads and executes file ‘base.m4’, defining various application
|
||
macros and computing other initializations. Once the input file
|
||
‘base.m4’ has been completely processed, GNU ‘m4’ produces in ‘base.m4f’
|
||
a “frozen” file, that is, a file which contains a kind of snapshot of
|
||
the ‘m4’ internal state.
|
||
|
||
Later calls, containing the ‘-R’ option, are able to reload the
|
||
internal state of ‘m4’, from ‘base.m4f’, _prior_ to reading any other
|
||
input files. This means instead of starting with a virgin copy of ‘m4’,
|
||
input will be read after having effectively recovered the effect of a
|
||
prior run. In our example, the effect is the same as if file ‘base.m4’
|
||
has been read anew. However, this effect is achieved a lot faster.
|
||
|
||
Only one frozen file may be created or read in any one ‘m4’
|
||
invocation. 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, if some care is taken,
|
||
the command:
|
||
|
||
$ m4 file1.m4 file2.m4 file3.m4 file4.m4
|
||
|
||
could be broken down in the following sequence, accumulating the same
|
||
output:
|
||
|
||
$ 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 for
|
||
this to work in all cases. In particular, the trace attribute of macros
|
||
is not handled, nor the current setting of ‘changeword’. Currently,
|
||
‘m4wrap’ and ‘sysval’ also have problems. Also, interactions for some
|
||
options of ‘m4’, being used in one call and not in the next, have not
|
||
been fully analyzed yet. On the other end, you may be confident that
|
||
stacks of ‘pushdef’ definitions are handled correctly, as well as
|
||
undefined or renamed builtins, and changed strings for quotes or
|
||
comments. And future releases of GNU M4 will improve on the utility of
|
||
frozen files.
|
||
|
||
When an ‘m4’ run is to be frozen, the automatic undiversion which
|
||
takes place at end of execution is inhibited. Instead, all positively
|
||
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 an ‘include’ file (*note
|
||
Search Path::).
|
||
|
||
If the frozen file was generated with a newer version of ‘m4’, and
|
||
contains directives that an older ‘m4’ cannot parse, attempting to load
|
||
the frozen file with option ‘-R’ will cause ‘m4’ to exit with status 63
|
||
to indicate version mismatch.
|
||
|
||
|
||
File: m4.info, Node: Frozen file format, Prev: Using frozen files, Up: Frozen files
|
||
|
||
15.2 Frozen file format
|
||
=======================
|
||
|
||
Frozen files are sharable across architectures. It is safe to write a
|
||
frozen file on one machine and read it on another, given that the second
|
||
machine uses the same or newer version of GNU ‘m4’. It is conventional,
|
||
but not required, to give a frozen file the suffix of ‘.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 they are not part of an embedded
|
||
string. In the following descriptions, each LEN refers to the length of
|
||
the corresponding strings STR in the next line of input. Numbers are
|
||
always expressed in decimal. There are no escape characters. The
|
||
directives are:
|
||
|
||
‘C LEN1 , LEN2 <NL> STR1 STR2 <NL>’
|
||
Uses STR1 and STR2 as the begin-comment and end-comment strings.
|
||
If omitted, then ‘#’ and <NL> are the comment delimiters.
|
||
|
||
‘D NUMBER, LEN <NL> STR <NL>’
|
||
Selects diversion NUMBER, making it current, then copy STR in the
|
||
current diversion. NUMBER may be a negative number for a
|
||
non-existing diversion. To merely specify an active selection, use
|
||
this command with an empty STR. With 0 as the diversion NUMBER,
|
||
STR will be issued on standard output at reload time. GNU ‘m4’
|
||
will not produce the ‘D’ directive with non-zero length for
|
||
diversion 0, but this can be done with manual edits. This
|
||
directive may appear more than once for the same diversion, in
|
||
which case the diversion is the concatenation of the various uses.
|
||
If omitted, then diversion 0 is current.
|
||
|
||
‘F LEN1 , LEN2 <NL> STR1 STR2 <NL>’
|
||
Defines, through ‘pushdef’, a definition for STR1 expanding to the
|
||
function whose builtin name is STR2. If the builtin does not exist
|
||
(for example, if the frozen file was produced by a copy of ‘m4’
|
||
compiled with changeword support, but the version of ‘m4’ reloading
|
||
was compiled without it), the reload is silent, but any subsequent
|
||
use of the definition of STR1 will result in a warning. This
|
||
directive may appear more than once for the same name, and its
|
||
order, along with ‘T’, is important. If omitted, you will have no
|
||
access to any builtins.
|
||
|
||
‘Q LEN1 , LEN2 <NL> STR1 STR2 <NL>’
|
||
Uses STR1 and STR2 as the begin-quote and end-quote strings. If
|
||
omitted, then ‘`’ and ‘'’ are the quote delimiters.
|
||
|
||
‘T LEN1 , LEN2 <NL> STR1 STR2 <NL>’
|
||
Defines, though ‘pushdef’, a definition for STR1 expanding to the
|
||
text given by STR2. This directive may appear more than once for
|
||
the same name, and its order, along with ‘F’, is important.
|
||
|
||
‘V NUMBER <NL>’
|
||
Confirms the format of the file. ‘m4’ 1.4.19 only creates and
|
||
understands frozen files where NUMBER is 1. This directive must be
|
||
the first non-comment in the file, and may not appear more than
|
||
once.
|
||
|
||
|
||
File: m4.info, Node: Compatibility, Next: Answers, Prev: Frozen files, Up: Top
|
||
|
||
16 Compatibility with other versions of ‘m4’
|
||
********************************************
|
||
|
||
This chapter describes the many of the differences between this
|
||
implementation of ‘m4’, and of other implementations found under UNIX,
|
||
such as System V Release 4, Solaris, and BSD flavors. In particular, it
|
||
lists the known differences and extensions to POSIX. However, the list
|
||
is not necessarily comprehensive.
|
||
|
||
At the time of this writing, POSIX 2001 (also known as IEEE Std
|
||
1003.1-2001) is the latest standard, although a new version of POSIX is
|
||
under development and includes several proposals for modifying what ‘m4’
|
||
is required to do. The requirements for ‘m4’ are shared between SUSv3
|
||
and POSIX, and can be viewed at
|
||
<https://www.opengroup.org/onlinepubs/000095399/utilities/m4.html>.
|
||
|
||
* Menu:
|
||
|
||
* Extensions:: Extensions in GNU M4
|
||
* Incompatibilities:: Facilities in System V m4 not in GNU M4
|
||
* Other Incompatibilities:: Other incompatibilities
|
||
|
||
|
||
File: m4.info, Node: Extensions, Next: Incompatibilities, Up: Compatibility
|
||
|
||
16.1 Extensions in GNU M4
|
||
=========================
|
||
|
||
This version of ‘m4’ contains a few facilities that do not exist in
|
||
System V ‘m4’. These extra facilities are all suppressed by using the
|
||
‘-G’ command line option (*note Invoking m4: Limits control.), unless
|
||
overridden by other command line options.
|
||
|
||
• In the ‘$N’ notation for macro arguments, N can contain several
|
||
digits, while the System V ‘m4’ only accepts one digit. This
|
||
allows macros in GNU ‘m4’ to take any number of arguments, and not
|
||
only nine (*note Arguments::).
|
||
|
||
This means that ‘define(`foo', `$11')’ is ambiguous between
|
||
implementations. To portably choose between grabbing the first
|
||
parameter and appending 1 to the expansion, or grabbing the
|
||
eleventh parameter, 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 (*note Shift::).
|
||
|
||
• The ‘divert’ (*note Divert::) macro can manage more than 9
|
||
diversions. GNU ‘m4’ treats all positive numbers as valid
|
||
diversions, rather than discarding diversions greater than 9.
|
||
|
||
• Files included with ‘include’ and ‘sinclude’ are sought in a user
|
||
specified search path, if they are not found in the working
|
||
directory. The search path is specified by the ‘-I’ option and the
|
||
‘M4PATH’ environment variable (*note Search Path::).
|
||
|
||
• Arguments to ‘undivert’ can be non-numeric, in which case the named
|
||
file will be included uninterpreted in the output (*note
|
||
Undivert::).
|
||
|
||
• Formatted output is supported through the ‘format’ builtin, which
|
||
is modeled after the C library function ‘printf’ (*note Format::).
|
||
|
||
• Searches and text substitution through basic regular expressions
|
||
are supported by the ‘regexp’ (*note Regexp::) and ‘patsubst’
|
||
(*note Patsubst::) builtins. Some BSD implementations use extended
|
||
regular expressions instead.
|
||
|
||
• The output of shell commands can be read into ‘m4’ with ‘esyscmd’
|
||
(*note Esyscmd::).
|
||
|
||
• There is indirect access to any builtin macro with ‘builtin’ (*note
|
||
Builtin::).
|
||
|
||
• Macros can be called indirectly through ‘indir’ (*note Indir::).
|
||
|
||
• The name of the program, the current input file, and the current
|
||
input line number are accessible through the builtins
|
||
‘__program__’, ‘__file__’, and ‘__line__’ (*note Location::).
|
||
|
||
• The format of the output from ‘dumpdef’ and macro tracing can be
|
||
controlled with ‘debugmode’ (*note Debug Levels::).
|
||
|
||
• The destination of trace and debug output can be controlled with
|
||
‘debugfile’ (*note Debug Output::).
|
||
|
||
• The ‘maketemp’ (*note Mkstemp::) macro behaves like ‘mkstemp’,
|
||
creating a new file with a unique name on every invocation, rather
|
||
than following the insecure behavior of replacing the trailing ‘X’
|
||
characters with the ‘m4’ process id.
|
||
|
||
• POSIX only requires support for the command line options ‘-s’,
|
||
‘-D’, and ‘-U’, so all other options accepted by GNU M4 are
|
||
extensions. *Note Invoking m4::, for a description of these
|
||
options.
|
||
|
||
The debugging and tracing facilities in GNU ‘m4’ are much more
|
||
extensive than in most other versions of ‘m4’.
|
||
|
||
|
||
File: m4.info, Node: Incompatibilities, Next: Other Incompatibilities, Prev: Extensions, Up: Compatibility
|
||
|
||
16.2 Facilities in System V ‘m4’ not in GNU ‘m4’
|
||
================================================
|
||
|
||
The version of ‘m4’ from System V contains a few facilities that have
|
||
not been implemented in GNU ‘m4’ yet. Additionally, POSIX requires some
|
||
behaviors that GNU ‘m4’ has not implemented yet. Relying on these
|
||
behaviors is non-portable, as a future release of GNU ‘m4’ may change.
|
||
|
||
• POSIX requires support for multiple arguments to ‘defn’, without
|
||
any clarification on how ‘defn’ behaves when one of the multiple
|
||
arguments names a builtin. System V ‘m4’ and some other
|
||
implementations allow mixing builtins and text macros into a single
|
||
macro. GNU ‘m4’ only supports joining multiple text arguments,
|
||
although a future implementation may lift this restriction to
|
||
behave more like System V. The only portable way to join text
|
||
macros with builtins is via helper macros and implicit
|
||
concatenation of macro results.
|
||
|
||
• POSIX requires an application to exit with non-zero status if it
|
||
wrote an error message to stderr. This has not yet been
|
||
consistently implemented for the various builtins that are required
|
||
to issue an error (such as ‘eval’ (*note Eval::) when an argument
|
||
cannot be parsed).
|
||
|
||
• Some traditional implementations only allow reading standard input
|
||
once, but GNU ‘m4’ correctly handles multiple instances of ‘-’ on
|
||
the command line.
|
||
|
||
• POSIX requires ‘m4wrap’ (*note M4wrap::) to act in FIFO (first-in,
|
||
first-out) order, but GNU ‘m4’ currently uses LIFO order.
|
||
Furthermore, POSIX states that only the first argument to ‘m4wrap’
|
||
is saved for later evaluation, but GNU ‘m4’ saves and processes all
|
||
arguments, with output separated by spaces.
|
||
|
||
• POSIX states that builtins that require arguments, but are called
|
||
without arguments, have undefined behavior. Traditional
|
||
implementations simply behave as though empty strings had been
|
||
passed. For example, ‘a`'define`'b’ would expand to ‘ab’. But GNU
|
||
‘m4’ ignores certain builtins if they have missing arguments,
|
||
giving ‘adefineb’ for the above example.
|
||
|
||
• Traditional implementations handle ‘define(`f',`1')’ (*note
|
||
Define::) by undefining the entire stack of previous definitions,
|
||
and if doing ‘undefine(`f')’ first. GNU ‘m4’ replaces just the top
|
||
definition on the stack, as if doing ‘popdef(`f')’ followed by
|
||
‘pushdef(`f',`1')’. POSIX allows either behavior.
|
||
|
||
• POSIX 2001 requires ‘syscmd’ (*note Syscmd::) to evaluate command
|
||
output for macro expansion, but this was a mistake that is
|
||
anticipated to be corrected in the next version of POSIX. GNU ‘m4’
|
||
follows traditional behavior in ‘syscmd’ where output is not
|
||
rescanned, and provides the extension ‘esyscmd’ that does scan the
|
||
output.
|
||
|
||
• At one point, POSIX required ‘changequote(ARG)’ (*note
|
||
Changequote::) to use newline as the close quote, but this was a
|
||
bug, and the next version of POSIX is anticipated to state that
|
||
using empty strings or just one argument is unspecified.
|
||
Meanwhile, the GNU ‘m4’ behavior of treating an empty end-quote
|
||
delimiter as ‘'’ is not portable, as Solaris treats it as repeating
|
||
the start-quote delimiter, and BSD treats it as leaving the
|
||
previous end-quote delimiter unchanged. For predictable results,
|
||
never call changequote with just one argument, or with empty
|
||
strings for arguments.
|
||
|
||
• At one point, POSIX required ‘changecom(ARG,)’ (*note Changecom::)
|
||
to make it impossible to end a comment, but this is a bug, and the
|
||
next version of POSIX is anticipated to state that using empty
|
||
strings is unspecified. Meanwhile, the GNU ‘m4’ behavior of
|
||
treating an empty end-comment delimiter as newline is not portable,
|
||
as BSD treats it as leaving the previous end-comment delimiter
|
||
unchanged. It is also impossible in BSD implementations to disable
|
||
comments, even though that is required by POSIX. For predictable
|
||
results, never call changecom with empty strings for arguments.
|
||
|
||
• Most implementations of ‘m4’ give macros a higher precedence than
|
||
comments when parsing, meaning that if the start delimiter given to
|
||
‘changecom’ (*note Changecom::) starts with a macro name, comments
|
||
are effectively disabled. POSIX does not specify what the
|
||
precedence is, so this version of GNU ‘m4’ parser recognizes
|
||
comments, then macros, then quoted strings.
|
||
|
||
• Traditional implementations allow argument collection, but not
|
||
string and comment processing, to span file boundaries. Thus, if
|
||
‘a.m4’ contains ‘len(’, and ‘b.m4’ contains ‘abc)’, ‘m4 a.m4 b.m4’
|
||
outputs ‘3’ with traditional ‘m4’, but gives an error message that
|
||
the end of file was encountered inside a macro with GNU ‘m4’. On
|
||
the other hand, traditional implementations do end of file
|
||
processing for files included with ‘include’ or ‘sinclude’ (*note
|
||
Include::), while GNU ‘m4’ seamlessly integrates the content of
|
||
those files. Thus ‘include(`a.m4')include(`b.m4')’ will output ‘3’
|
||
instead of giving an error.
|
||
|
||
• Traditional ‘m4’ treats ‘traceon’ (*note Trace::) without arguments
|
||
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 GNU ‘m4’ encounters ‘traceon’ without
|
||
arguments, it turns tracing on for all existing definitions at the
|
||
time, but does not trace future definitions; ‘traceoff’ without
|
||
arguments turns tracing off for all definitions regardless of
|
||
whether they were also traced by name; and tracing by name, such as
|
||
with ‘-tfoo’ at the command line or ‘traceon(`foo')’ in the input,
|
||
is an attribute that is preserved even if the macro is currently
|
||
undefined.
|
||
|
||
Additionally, while POSIX requires trace output, it makes no
|
||
demands on the formatting of that output. Parsing trace output is
|
||
not guaranteed to be reliable, even between different releases of
|
||
GNU M4; however, the intent is that any future changes in trace
|
||
output will only occur under the direction of additional
|
||
‘debugmode’ flags (*note Debug Levels::).
|
||
|
||
• POSIX requires ‘eval’ (*note Eval::) to treat all operators with
|
||
the same precedence as C. However, earlier versions of GNU ‘m4’
|
||
followed the traditional behavior of other ‘m4’ implementations,
|
||
where bitwise and logical negation (‘~’ and ‘!’) have lower
|
||
precedence than equality operators; and where equality operators
|
||
(‘==’ and ‘!=’) had the same precedence as relational operators
|
||
(such as ‘<’). Use explicit parentheses to ensure proper
|
||
precedence. As extensions to POSIX, GNU ‘m4’ gives well-defined
|
||
semantics to operations that C leaves undefined, such as when
|
||
overflow occurs, when shifting negative numbers, or when performing
|
||
division by zero. POSIX also requires ‘=’ to cause an error, but
|
||
many traditional implementations allowed it as an alias for ‘==’.
|
||
|
||
• POSIX 2001 requires ‘translit’ (*note Translit::) to treat each
|
||
character of the second and third arguments literally. However, it
|
||
is anticipated that the next version of POSIX will allow the GNU
|
||
‘m4’ behavior of treating ‘-’ as a range operator.
|
||
|
||
• POSIX requires ‘m4’ to honor the locale environment variables of
|
||
‘LANG’, ‘LC_ALL’, ‘LC_CTYPE’, ‘LC_MESSAGES’, and ‘NLSPATH’, but
|
||
this has not yet been implemented in GNU ‘m4’.
|
||
|
||
• 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 most traditional
|
||
implementations also ignore all whitespace (formfeed, carriage
|
||
return, and vertical tab). GNU ‘m4’ follows tradition and ignores
|
||
all leading unquoted whitespace.
|
||
|
||
• A strictly-compliant POSIX client is not allowed to use
|
||
command-line arguments not specified by POSIX. However, since this
|
||
version of M4 ignores ‘POSIXLY_CORRECT’ and enables the option
|
||
‘--gnu’ by default (*note Invoking m4: Limits control.), a client
|
||
desiring to be strictly compliant has no way to disable GNU
|
||
extensions that conflict with POSIX when directly invoking the
|
||
compiled ‘m4’. A future version of ‘GNU’ M4 will honor the
|
||
environment variable ‘POSIXLY_CORRECT’, implicitly enabling
|
||
‘--traditional’ if it is set, in order to allow a
|
||
strictly-compliant client. In the meantime, a client needing
|
||
strict POSIX compliance can use the workaround of invoking a shell
|
||
script wrapper, where the wrapper then adds ‘--traditional’ to the
|
||
arguments passed to the compiled ‘m4’.
|
||
|
||
|
||
File: m4.info, Node: Other Incompatibilities, Prev: Incompatibilities, Up: Compatibility
|
||
|
||
16.3 Other incompatibilities
|
||
============================
|
||
|
||
There are a few other incompatibilities between this implementation of
|
||
‘m4’, and the System V version.
|
||
|
||
• GNU ‘m4’ implements sync lines differently from System V ‘m4’, when
|
||
text is being diverted. GNU ‘m4’ outputs the sync lines when the
|
||
text is being diverted, and System V ‘m4’ when the diverted text is
|
||
being brought back.
|
||
|
||
The problem is which lines and file names should be attached to
|
||
text that is being, or has been, diverted. System V ‘m4’ regards
|
||
all the diverted text as being generated by the source line
|
||
containing the ‘undivert’ call, whereas GNU ‘m4’ regards the
|
||
diverted text as being generated at the time it is diverted.
|
||
|
||
The sync line option is used mostly when using ‘m4’ as a front end
|
||
to a compiler. If a diverted line causes a compiler error, the
|
||
error messages should most probably refer to the place where the
|
||
diversion 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 syncline
|
||
output at the start of each diversion occurs no matter what, even
|
||
if the previous diversion did not end with a newline. This goes
|
||
contrary to the claim that synclines appear on a line by
|
||
themselves, so this limitation may be corrected in a future version
|
||
of ‘m4’. In the meantime, when using ‘-s’, it is wisest to make
|
||
sure all diversions end with newline.
|
||
|
||
• GNU ‘m4’ makes no attempt at prohibiting self-referential
|
||
definitions like:
|
||
|
||
define(`x', `x')
|
||
⇒
|
||
define(`x', `x ')
|
||
⇒
|
||
|
||
There is nothing inherently wrong with defining ‘x’ to return ‘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 for variables 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
|
||
name would be a useless limitation. Of course, this leaves more
|
||
rope for the GNU ‘m4’ user to hang himself! Rescanning hangs may
|
||
be avoided through careful programming, a little like for endless
|
||
loops in traditional programming languages.
|
||
|
||
|
||
File: m4.info, Node: Answers, Next: Copying This Package, Prev: Compatibility, Up: Top
|
||
|
||
17 Correct version of some examples
|
||
***********************************
|
||
|
||
Some of the examples in this manuals are buggy or not very robust, for
|
||
demonstration purposes. Improved versions of these composite macros are
|
||
presented here.
|
||
|
||
* Menu:
|
||
|
||
* Improved exch:: Solution for ‘exch’
|
||
* Improved forloop:: Solution for ‘forloop’
|
||
* Improved foreach:: Solution for ‘foreach’
|
||
* Improved copy:: Solution for ‘copy’
|
||
* Improved m4wrap:: Solution for ‘m4wrap’
|
||
* Improved cleardivert:: Solution for ‘cleardivert’
|
||
* Improved capitalize:: Solution for ‘capitalize’
|
||
* Improved fatal_error:: Solution for ‘fatal_error’
|
||
|
||
|
||
File: m4.info, Node: Improved exch, Next: Improved forloop, Up: Answers
|
||
|
||
17.1 Solution for ‘exch’
|
||
========================
|
||
|
||
The ‘exch’ macro (*note Arguments::) as presented requires clients to
|
||
double quote their arguments. A nicer definition, which lets clients
|
||
follow the rule of thumb of one level of quoting per level of
|
||
parentheses, involves adding quotes in the definition of ‘exch’, as
|
||
follows:
|
||
|
||
define(`exch', ``$2', `$1'')
|
||
⇒
|
||
define(exch(`expansion text', `macro'))
|
||
⇒
|
||
macro
|
||
⇒expansion text
|
||
|
||
|
||
File: m4.info, Node: Improved forloop, Next: Improved foreach, Prev: Improved exch, Up: Answers
|
||
|
||
17.2 Solution for ‘forloop’
|
||
===========================
|
||
|
||
The ‘forloop’ macro (*note Forloop::) as presented earlier can go into
|
||
an infinite loop if given an iterator that is not parsed as a macro
|
||
name. It does not do any sanity checking on its numeric bounds, and
|
||
only permits decimal numbers for bounds. Here is an improved version,
|
||
shipped as ‘m4-1.4.19/examples/forloop2.m4’; this version also optimizes
|
||
overhead by calling four macros instead of six per iteration (excluding
|
||
those in TEXT), by not dereferencing the ITERATOR 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 be
|
||
uniformly transformed. The following example shows a transformation
|
||
that doubles the current quoting and appends a suffix ‘2’ to each
|
||
transformed macro. If ‘foreach’ refers to the literal ‘_foreach’, then
|
||
‘foreach2’ invokes ‘_foreach’ instead of the intended ‘_foreach2’, and
|
||
the mixing of quoting paradigms leads to 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 repeatedly
|
||
assigning a variable then invoking or dereferencing it, it is possible
|
||
to pass the current iterator value as a single argument. Coupled with
|
||
‘curry’ if other arguments are needed (*note Composition::), or with
|
||
helper macros if the argument is needed in more than one place in the
|
||
expansion, the output can be generated with three, rather than four,
|
||
macros of overhead per iteration. Notice how the file
|
||
‘m4-1.4.19/examples/forloop3.m4’ rearranges the arguments of the helper
|
||
‘_forloop’ to take two arguments that are placed around the current
|
||
value. By splitting a balanced set of parantheses across multiple
|
||
arguments, the helper macro can now be shared by ‘forloop’ 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 as
|
||
adding an optional step argument, or allowing iteration through
|
||
descending sequences. GNU Autoconf provides some of these additional
|
||
bells and whistles in its ‘m4_for’ macro.
|
||
|
||
|
||
File: m4.info, Node: Improved foreach, Next: Improved copy, Prev: Improved forloop, Up: Answers
|
||
|
||
17.3 Solution for ‘foreach’
|
||
===========================
|
||
|
||
The ‘foreach’ and ‘foreachq’ macros (*note Foreach::) as presented
|
||
earlier each have flaws. First, we will examine and fix the quadratic
|
||
behavior of ‘foreachq’:
|
||
|
||
$ 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 quoted ‘shift’ invocations,
|
||
and the entire list contents were passing through every iteration. In
|
||
general, when recursing, it is a good idea to make the recursion use
|
||
fewer arguments, rather than adding additional quoted uses of ‘shift’.
|
||
By doing so, ‘m4’ uses less memory, invokes fewer macros, is less likely
|
||
to run into machine limits, and most importantly, performs faster. The
|
||
fixed version of ‘foreachq’ can be found in
|
||
‘m4-1.4.19/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 macros in turn
|
||
must re-supply the layer of quotes lost in the macro invocation.
|
||
Contrast the use of ‘_arg1q’, which quotes the first list element, with
|
||
‘_arg1’ of the earlier implementation that returned the first list
|
||
element directly. Additionally, by calling the helper method
|
||
immediately, the ‘defn(`ITERATOR')’ no longer contains unexpanded
|
||
macros.
|
||
|
||
The astute m4 programmer might notice that the solution above still
|
||
uses more memory and macro invocations, and thus more time, than
|
||
strictly necessary. Note that ‘$2’, which contains an arbitrarily long
|
||
quoted list, is expanded and rescanned three times per iteration of
|
||
‘_foreachq’. Furthermore, every iteration of the algorithm effectively
|
||
unboxes then reboxes the list, which costs a couple of macro
|
||
invocations. It is possible to rewrite the algorithm for a bit more
|
||
speed by swapping the order of the arguments to ‘_foreachq’ in order to
|
||
operate on an unboxed list in the first place, and by using the
|
||
fixed-length ‘$#’ instead of an arbitrary length list as the key to end
|
||
recursion. The result is an overhead of six macro invocations per loop
|
||
(excluding any macros in TEXT), instead of eight. This alternative
|
||
approach is available as ‘m4-1.4.19/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 rescanned as
|
||
it is encountered. Thus, the ‘foreachq3.m4’ alternative uses much less
|
||
memory than ‘foreachq2.m4’, and executes as much as 10% faster, since
|
||
each iteration encounters fewer ‘$@’. However, the implementation of
|
||
rescanning every byte in ‘$@’ is quadratic in the number of bytes
|
||
scanned (for example, making the broken version in ‘foreachq.m4’ cubic,
|
||
rather than quadratic, in behavior). A future release of M4 will
|
||
improve the underlying implementation by reusing results of previous
|
||
scans, so that both styles of ‘foreachq’ can become linear in the number
|
||
of bytes scanned. Notice how the implementation injects an empty
|
||
argument prior to expanding ‘$2’ within ‘foreachq’; the helper macro
|
||
‘_foreachq’ then ignores the third argument altogether, and ends
|
||
recursion when there are three arguments left because there was nothing
|
||
left to pass through ‘shift’. Thus, each iteration only needs one
|
||
‘ifelse’, rather than the two conditionals used in the version from
|
||
‘foreachq2.m4’.
|
||
|
||
So far, all of the implementations of ‘foreachq’ presented have been
|
||
quadratic with M4 1.4.x. But ‘forloop’ is linear, because each
|
||
iteration parses a constant amount of arguments. So, it is possible to
|
||
design a variant that uses ‘forloop’ to do the iteration, then uses ‘$@’
|
||
only once at the end, giving a linear result even with older M4
|
||
implementations. This implementation relies on the GNU extension that
|
||
‘$10’ expands to the tenth argument rather than the first argument
|
||
concatenated with ‘0’. The trick is to define an intermediate macro
|
||
that repeats the text ‘m4_define(`$1', `$N')$2`'’, with ‘n’ set to
|
||
successive integers corresponding to each argument. The helper macro
|
||
‘_foreachq_’ is needed in order to generate the literal sequences such
|
||
as ‘$1’ into the intermediate macro, rather than expanding them as the
|
||
arguments of ‘_foreachq’. With this approach, no ‘shift’ calls are even
|
||
needed! Even though there are seven macros of overhead per iteration
|
||
instead of six in ‘foreachq3.m4’, the linear scaling is apparent at
|
||
relatively small list sizes. However, this approach will need
|
||
adjustment when a future version of M4 follows POSIX by no longer
|
||
treating ‘$10’ as the tenth argument; the anticipation is that ‘${10}’
|
||
can be used instead, although that 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 in ‘m4-1.4.19/examples/foreach2.m4’, simply overquotes the
|
||
arguments to ‘_foreach’ to begin with, using ‘dquote_elt’. Then
|
||
‘_foreach’ can just use ‘_arg1’ to remove the extra layer of quoting
|
||
that was added up front:
|
||
|
||
$ 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’ that performs
|
||
in linear time on M4 1.4.x; the easiest method is probably writing a
|
||
version of ‘foreach’ that unboxes its list, then invokes ‘_foreachq’ as
|
||
previously defined in ‘foreachq4.m4’.
|
||
|
||
In summary, recursion over list elements is trickier than it appeared
|
||
at first glance, but provides a powerful idiom within ‘m4’ processing.
|
||
As a final demonstration, both list styles are now able to handle
|
||
several scenarios that would wreak havoc on one or both of the original
|
||
implementations. This points out one other difference between the list
|
||
styles. ‘foreach’ evaluates unquoted list elements only once, in
|
||
preparation for calling ‘_foreach’, similary for ‘foreachq’ as provided
|
||
by ‘foreachq3.m4’ or ‘foreachq4.m4’. But ‘foreachq’, as provided by
|
||
‘foreachq2.m4’, evaluates unquoted list elements twice while visiting
|
||
the first list element, once in ‘_arg1q’ and once in ‘_rest’. When
|
||
deciding which list style to use, one must take into account whether
|
||
repeating the side effects of unquoted list elements will have any
|
||
detrimental 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>
|
||
|
||
|
||
File: m4.info, Node: Improved copy, Next: Improved m4wrap, Prev: Improved foreach, Up: Answers
|
||
|
||
17.4 Solution for ‘copy’
|
||
========================
|
||
|
||
The macro ‘copy’ presented above is unable to handle builtin tokens with
|
||
M4 1.4.x, because it tries to pass the builtin token through the macro
|
||
‘curry’, where it is silently flattened to an empty string (*note
|
||
Composition::). Rather than using the problematic ‘curry’ to work
|
||
around the limitation that ‘stack_foreach’ expects to invoke a macro
|
||
that takes exactly one argument, we can write a new macro that lets us
|
||
form the exact two-argument ‘pushdef’ call sequence needed, so that we
|
||
are no longer 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, expand SEP
|
||
between definitions. ‘stack_foreach_sep’ visits the oldest
|
||
definition first, while ‘stack_foreach_sep_lifo’ visits the current
|
||
definition first. The expansion may dereference MACRO, but should
|
||
not modify it. There are a few special macros, such as ‘defn’,
|
||
which cannot be used as the MACRO parameter.
|
||
|
||
Note that ‘stack_foreach(`MACRO', `ACTION')’ is equivalent to
|
||
‘stack_foreach_sep(`MACRO', `ACTION(', `)')’. By supplying explicit
|
||
parentheses, split among the PRE and POST arguments to
|
||
‘stack_foreach_sep’, it is now possible to construct macro calls with
|
||
more than one argument, without passing builtin tokens through a macro
|
||
call. It is likewise possible to directly reference the stack
|
||
definitions without a macro call, by leaving PRE and POST empty. Thus,
|
||
in addition to fixing ‘copy’ on builtin tokens, it also executes with
|
||
fewer macro invocations.
|
||
|
||
The new macro also adds a separator that is only output after the
|
||
first iteration of the helper ‘_stack_reverse_sep’, implemented by
|
||
prepending the original SEP to PRE and omitting a SEP argument in
|
||
subsequent iterations. Note that the empty string that separates SEP
|
||
from PRE is provided as part of the fourth argument when originally
|
||
calling ‘_stack_reverse_sep’, and not by writing ‘$4`'$3’ as the third
|
||
argument in the recursive call; while the other approach would give the
|
||
same output, it does so at the expense of increasing the argument size
|
||
on each iteration of ‘_stack_reverse_sep’, which results in quadratic
|
||
instead of linear execution time. The improved stack walking macros are
|
||
available in ‘m4-1.4.19/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
|
||
|
||
|
||
File: m4.info, Node: Improved m4wrap, Next: Improved cleardivert, Prev: Improved copy, Up: Answers
|
||
|
||
17.5 Solution for ‘m4wrap’
|
||
==========================
|
||
|
||
The replacement ‘m4wrap’ versions presented above, designed to guarantee
|
||
FIFO or LIFO order regardless of the underlying M4 implementation, share
|
||
a bug when dealing with wrapped text that looks like parameter
|
||
expansion. Note how the invocation of ‘m4wrapN’ interprets these
|
||
parameters, while using the builtin 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 of
|
||
multiple ‘m4wrapN’ placeholders in the original examples is more
|
||
expensive in time and memory than strictly necessary. Notice how the
|
||
improved version grabs the wrapped text via ‘defn’ to avoid parameter
|
||
expansion, then undefines ‘_m4wrap_text’, before stripping a level of
|
||
quotes with ‘_arg1’ to expand the text. That way, each level of
|
||
wrapping reuses the single placeholder, which starts each nesting level
|
||
in an undefined state.
|
||
|
||
Finally, it is worth emulating the GNU M4 extension of saving all
|
||
arguments to ‘m4wrap’, separated by a space, rather than saving just the
|
||
first argument. This is done with the ‘join’ macro documented
|
||
previously (*note Shift::). The improved LIFO example is shipped as
|
||
‘m4-1.4.19/examples/wraplifo2.m4’, and can easily be converted to a FIFO
|
||
solution by swapping the adjacent invocations of ‘joinall’ 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 $@
|
||
|
||
|
||
File: m4.info, Node: Improved cleardivert, Next: Improved capitalize, Prev: Improved m4wrap, Up: Answers
|
||
|
||
17.6 Solution for ‘cleardivert’
|
||
===============================
|
||
|
||
The ‘cleardivert’ macro (*note Cleardivert::) cannot, as it stands, be
|
||
called without arguments to clear all pending diversions. That is
|
||
because using undivert with an empty string for an argument is different
|
||
than using it with no arguments at all. Compare the earlier definition
|
||
with 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
|
||
⇒
|
||
|
||
|
||
File: m4.info, Node: Improved capitalize, Next: Improved fatal_error, Prev: Improved cleardivert, Up: Answers
|
||
|
||
17.7 Solution for ‘capitalize’
|
||
==============================
|
||
|
||
The ‘capitalize’ macro (*note Patsubst::) as presented earlier does not
|
||
allow clients to follow the quoting rule of thumb. Consider the three
|
||
macros ‘active’, ‘Active’, and ‘ACTIVE’, and the difference between
|
||
calling ‘capitalize’ with the expansion of a macro, expanding the result
|
||
of a case change, and changing the case of a double-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, it
|
||
was throwing away later arguments, whereas ‘upcase’ and ‘downcase’ 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 impossible to
|
||
invoke ‘Active’ after the fact, and allowing the alternate macro ‘A’ to
|
||
interfere. Here, the solution is to use additional quoting in the
|
||
helper macros, then pass the final over-quoted output string through
|
||
‘_arg1’ to remove the extra quoting and finally invoke the concatenated
|
||
portions as a single string.
|
||
|
||
Finally, when passed a double-quoted string, the nested macro
|
||
‘_capitalize’ is never invoked because it ended up nested inside quotes.
|
||
This one is the toughest to fix. In short, we have no idea how many
|
||
levels of quotes are in effect on the substring being altered by
|
||
‘patsubst’. If the replacement string cannot be expressed entirely in
|
||
terms of literal text and backslash substitutions, then we need a
|
||
mechanism to guarantee that the helper macros are invoked outside of
|
||
quotes. In other words, this sounds like a job for ‘changequote’ (*note
|
||
Changequote::). By changing the active quoting characters, we can
|
||
guarantee that replacement text injected by ‘patsubst’ always occurs in
|
||
the middle of a string that has exactly one level of over-quoting using
|
||
alternate quotes; so the replacement text closes the quoted string,
|
||
invokes the helper macros, then reopens the quoted string. In turn,
|
||
that means the replacement text has unbalanced quotes, necessitating
|
||
another round of ‘changequote’.
|
||
|
||
In the fixed version below, (also shipped as
|
||
‘m4-1.4.19/examples/capitalize2.m4’), ‘capitalize’ uses the alternate
|
||
quotes of ‘<<[’ and ‘]>>’ (the longer strings are chosen so as to be
|
||
less likely to appear in the text being converted). The helpers
|
||
‘_to_alt’ and ‘_from_alt’ merely reduce the number of characters
|
||
required to perform a ‘changequote’, since the definition changes twice.
|
||
The outermost pair means that ‘patsubst’ and ‘_capitalize_alt’ are
|
||
invoked with alternate quoting; the innermost pair is used so that the
|
||
third argument to ‘patsubst’ can contain an unbalanced ‘]>>’/‘<<[’ pair.
|
||
Note that ‘upcase’ and ‘downcase’ must be redefined as ‘_upcase_alt’ and
|
||
‘_downcase_alt’, since they contain nested quotes but are invoked with
|
||
the alternate quoting scheme 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
|
||
|
||
|
||
File: m4.info, Node: Improved fatal_error, Prev: Improved capitalize, Up: Answers
|
||
|
||
17.8 Solution for ‘fatal_error’
|
||
===============================
|
||
|
||
The ‘fatal_error’ macro (*note M4exit::) is not robust to versions of
|
||
GNU M4 earlier than 1.4.8, where invoking ‘__file__’ (*note Location::)
|
||
inside ‘m4wrap’ would result in an empty string, and ‘__line__’ resulted
|
||
in ‘0’ even though all files start at line 1. Furthermore, versions
|
||
earlier than 1.4.6 did not support the ‘__program__’ macro. If you want
|
||
‘fatal_error’ to work across the entire 1.4.x release series, a better
|
||
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
|
||
|
||
|
||
File: m4.info, Node: Copying This Package, Next: Copying This Manual, Prev: 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 the
|
||
overall M4 package. This manual is under a different set of
|
||
restrictions, covered later (*note Copying This Manual::).
|
||
|
||
* Menu:
|
||
|
||
* GNU General Public License:: License for copying the M4 package
|
||
|
||
|
||
File: m4.info, Node: GNU General Public License, Up: Copying This Package
|
||
|
||
A.1 License for copying the M4 package
|
||
======================================
|
||
|
||
Version 3, 29 June 2007
|
||
|
||
Copyright © 2007 Free Software Foundation, Inc. <https://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 for software
|
||
and other kinds of works.
|
||
|
||
The licenses for most software and other practical works are designed
|
||
to take away your freedom to share and change the works. By contrast,
|
||
the GNU General Public License is intended to guarantee your freedom to
|
||
share and change all versions of a program—to make sure it remains free
|
||
software for all its users. We, the Free Software Foundation, use the
|
||
GNU General Public License for most of our software; it applies also to
|
||
any other work released this way by its authors. You can apply it to
|
||
your programs, too.
|
||
|
||
When we speak of free software, we are referring to freedom, not
|
||
price. Our General Public Licenses are designed to make sure that you
|
||
have the freedom to distribute copies of free software (and charge for
|
||
them if you wish), that you receive source code or can get it if you
|
||
want it, that you can change the software or use pieces of it in new
|
||
free programs, and that you know you can do these things.
|
||
|
||
To protect your rights, we need to prevent others from denying you
|
||
these rights or asking you to surrender the rights. Therefore, you have
|
||
certain responsibilities if you distribute copies of the software, or if
|
||
you modify it: responsibilities to respect the freedom of others.
|
||
|
||
For example, if you distribute copies of such a program, whether
|
||
gratis or for a fee, you must pass on to the recipients the same
|
||
freedoms that you received. You must make sure that they, too, receive
|
||
or can get the source code. And you must show them these terms 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 License
|
||
giving you legal permission to copy, distribute and/or modify it.
|
||
|
||
For the developers’ and authors’ protection, the GPL clearly explains
|
||
that there is no warranty for this free software. For both users’ and
|
||
authors’ sake, the GPL requires that modified versions be marked as
|
||
changed, so that their problems will not be attributed erroneously to
|
||
authors of previous versions.
|
||
|
||
Some devices are designed to deny users access to install or run
|
||
modified versions of the software inside them, although the manufacturer
|
||
can do so. This is fundamentally incompatible with the aim of
|
||
protecting users’ freedom to change the software. The systematic
|
||
pattern of such abuse occurs in the area of products for individuals to
|
||
use, which is precisely where it is most unacceptable. Therefore, we
|
||
have designed this version of the GPL to prohibit the practice for those
|
||
products. If such problems arise substantially in other domains, we
|
||
stand ready to extend this provision to those domains in future versions
|
||
of the GPL, as needed to protect the freedom of users.
|
||
|
||
Finally, every program is threatened constantly by software patents.
|
||
States should not allow patents to restrict development and use of
|
||
software on general-purpose computers, but in those that do, we wish to
|
||
avoid the special danger that patents applied to a free program could
|
||
make it effectively proprietary. To prevent this, the GPL assures that
|
||
patents cannot be used to render the program non-free.
|
||
|
||
The precise terms and conditions for copying, distribution and
|
||
modification follow.
|
||
|
||
TERMS AND CONDITIONS
|
||
====================
|
||
|
||
0. Definitions.
|
||
|
||
“This License” refers to version 3 of the GNU General Public
|
||
License.
|
||
|
||
“Copyright” also means copyright-like laws that apply to other
|
||
kinds of works, such as semiconductor masks.
|
||
|
||
“The Program” refers to any copyrightable work licensed under this
|
||
License. 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
|
||
work in a fashion requiring copyright permission, other than the
|
||
making of an exact copy. The resulting work is called a “modified
|
||
version” of the earlier work or a work “based on” the earlier work.
|
||
|
||
A “covered work” means either the unmodified Program or a work
|
||
based on the Program.
|
||
|
||
To “propagate” a work means to do anything with it that, without
|
||
permission, would make you directly or secondarily liable for
|
||
infringement under applicable copyright law, except executing it on
|
||
a computer or modifying a private copy. Propagation includes
|
||
copying, distribution (with or without modification), making
|
||
available to the public, and in some countries other activities as
|
||
well.
|
||
|
||
To “convey” a work means any kind of propagation that enables other
|
||
parties to make or receive copies. Mere interaction with a user
|
||
through a computer network, with no transfer of a copy, is not
|
||
conveying.
|
||
|
||
An interactive user interface displays “Appropriate Legal Notices”
|
||
to the extent that it includes a convenient and prominently visible
|
||
feature that (1) displays an appropriate copyright notice, and (2)
|
||
tells the user that there is no warranty for the work (except to
|
||
the extent that warranties are provided), that licensees may convey
|
||
the work under this License, and how to view a copy of this
|
||
License. If the interface presents a list of user commands or
|
||
options, such as a menu, a prominent item in the list meets this
|
||
criterion.
|
||
|
||
1. Source Code.
|
||
|
||
The “source code” for a work means the preferred form of the work
|
||
for making modifications to it. “Object code” means any non-source
|
||
form of a work.
|
||
|
||
A “Standard Interface” means an interface that either is an
|
||
official standard defined by a recognized standards body, or, in
|
||
the case of interfaces specified for a particular programming
|
||
language, one that is widely used among developers working in that
|
||
language.
|
||
|
||
The “System Libraries” of an executable work include anything,
|
||
other than the work as a whole, that (a) is included in the normal
|
||
form of packaging a Major Component, but which is not part of that
|
||
Major Component, and (b) serves only to enable use of the work with
|
||
that Major Component, or to implement a Standard Interface for
|
||
which an implementation 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 to produce the work, or an object code
|
||
interpreter used to run it.
|
||
|
||
The “Corresponding Source” for a work in object code form means all
|
||
the source code needed to generate, install, and (for an executable
|
||
work) run the object code and to modify the work, including scripts
|
||
to control those activities. However, it does not include the
|
||
work’s System Libraries, or general-purpose tools or generally
|
||
available free programs which are used unmodified in performing
|
||
those activities but which are not part of the work. For example,
|
||
Corresponding Source includes interface definition files associated
|
||
with source files for the work, and the source code for shared
|
||
libraries and dynamically linked subprograms that the work is
|
||
specifically designed to require, such as by intimate data
|
||
communication or control flow between those subprograms and other
|
||
parts of the work.
|
||
|
||
The Corresponding Source need not include anything that users can
|
||
regenerate automatically from other parts of the Corresponding
|
||
Source.
|
||
|
||
The Corresponding Source for a work in source code form is that
|
||
same work.
|
||
|
||
2. Basic Permissions.
|
||
|
||
All rights granted under this License are granted for the term of
|
||
copyright on the Program, and are irrevocable provided the stated
|
||
conditions are met. This License explicitly affirms your unlimited
|
||
permission to run the unmodified Program. The output from running
|
||
a covered work is covered by this License only if the output, given
|
||
its content, constitutes a covered work. This License acknowledges
|
||
your rights 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 having them make modifications exclusively for you,
|
||
or provide you with facilities for running those works, provided
|
||
that you comply with the terms of this License in conveying all
|
||
material for which you do not control copyright. Those thus making
|
||
or running the covered works for you must do so exclusively on your
|
||
behalf, under your direction and control, on terms that prohibit
|
||
them from making any copies of your copyrighted material outside
|
||
their relationship with you.
|
||
|
||
Conveying under any other circumstances is permitted solely under
|
||
the conditions stated below. Sublicensing is not allowed; section
|
||
10 makes it unnecessary.
|
||
|
||
3. Protecting Users’ Legal Rights From Anti-Circumvention Law.
|
||
|
||
No covered work shall be deemed part of an effective technological
|
||
measure under any applicable law fulfilling obligations under
|
||
article 11 of the WIPO copyright treaty adopted on 20 December
|
||
1996, or similar laws prohibiting or restricting circumvention of
|
||
such measures.
|
||
|
||
When you convey a covered work, you waive any legal power to forbid
|
||
circumvention of technological measures to the extent such
|
||
circumvention is effected by exercising rights under this License
|
||
with respect to the covered work, and you disclaim any intention to
|
||
limit operation or modification of the work as a means of
|
||
enforcing, against the work’s users, your or third parties’ legal
|
||
rights to forbid circumvention of technological measures.
|
||
|
||
4. Conveying Verbatim Copies.
|
||
|
||
You may convey verbatim copies of the Program’s source code as you
|
||
receive it, in any medium, provided that you conspicuously and
|
||
appropriately publish on each copy an appropriate copyright notice;
|
||
keep intact all notices stating that this License and any
|
||
non-permissive terms added in accord with section 7 apply to the
|
||
code; keep intact all notices of the absence of any warranty; and
|
||
give all recipients 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.
|
||
|
||
5. Conveying Modified Source Versions.
|
||
|
||
You may convey a work based on the Program, or the modifications to
|
||
produce it from the Program, in the form of source code under the
|
||
terms of section 4, provided that you also meet all of these
|
||
conditions:
|
||
|
||
a. The work must carry prominent notices stating that you
|
||
modified it, and giving a relevant date.
|
||
|
||
b. The work must carry prominent notices stating that it is
|
||
released under this License and any conditions added under
|
||
section 7. This requirement modifies the requirement in
|
||
section 4 to “keep intact all notices”.
|
||
|
||
c. You must license the entire work, as a whole, under this
|
||
License to anyone who comes into possession of a copy. This
|
||
License will therefore apply, along with any applicable
|
||
section 7 additional terms, to the whole of the work, and all
|
||
its parts, regardless of how they are packaged. This License
|
||
gives no permission to license the work in any other way, but
|
||
it does not invalidate such permission if you have separately
|
||
received it.
|
||
|
||
d. If the work has interactive user interfaces, each must display
|
||
Appropriate Legal Notices; however, if the Program has
|
||
interactive interfaces that do not display Appropriate Legal
|
||
Notices, your work need not make them do so.
|
||
|
||
A compilation of a covered work with other separate and independent
|
||
works, 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 not used to limit the access or legal rights of the
|
||
compilation’s users beyond what the individual works permit.
|
||
Inclusion of a covered work in an aggregate does not cause this
|
||
License to apply to the other parts of the aggregate.
|
||
|
||
6. Conveying Non-Source Forms.
|
||
|
||
You may convey a covered work in object code form under the terms
|
||
of sections 4 and 5, provided that you also convey the
|
||
machine-readable Corresponding Source under the terms of this
|
||
License, in one of these ways:
|
||
|
||
a. Convey the object code in, or embodied in, a physical product
|
||
(including a physical distribution medium), accompanied by the
|
||
Corresponding Source fixed on a durable physical medium
|
||
customarily used for software interchange.
|
||
|
||
b. Convey the object code in, or embodied in, a physical product
|
||
(including a physical distribution medium), accompanied by a
|
||
written offer, valid for at least three years and valid for as
|
||
long as you offer spare parts or customer support for that
|
||
product model, to give anyone who possesses the object code
|
||
either (1) a copy of the Corresponding Source for all the
|
||
software in the product that is covered by this License, on a
|
||
durable physical medium customarily used for software
|
||
interchange, for a price no more than your reasonable cost of
|
||
physically performing this conveying of source, or (2) access
|
||
to copy the Corresponding Source from a network server at no
|
||
charge.
|
||
|
||
c. Convey individual copies of the object code with a copy of the
|
||
written offer to provide the Corresponding Source. This
|
||
alternative is allowed only occasionally and noncommercially,
|
||
and only if you received the object code with such an offer,
|
||
in accord with subsection 6b.
|
||
|
||
d. Convey the object code by offering access from a designated
|
||
place (gratis or for a charge), and offer equivalent access to
|
||
the Corresponding Source in the same way through the same
|
||
place at no further charge. You need not require recipients
|
||
to copy the Corresponding Source along with the object code.
|
||
If the place to copy the object code is a network server, the
|
||
Corresponding Source may be on a different server (operated by
|
||
you or a third party) that supports equivalent copying
|
||
facilities, provided you maintain clear directions next to the
|
||
object code saying where to find the Corresponding Source.
|
||
Regardless of what server hosts the Corresponding Source, you
|
||
remain obligated to ensure that it is available for as long as
|
||
needed to satisfy these requirements.
|
||
|
||
e. Convey the object code using peer-to-peer transmission,
|
||
provided you inform other peers where the object code and
|
||
Corresponding Source of the work are being offered to the
|
||
general public at no charge under subsection 6d.
|
||
|
||
A separable portion of the object code, whose source code is
|
||
excluded from the Corresponding Source as a System Library, need
|
||
not be included in conveying the object code work.
|
||
|
||
A “User Product” is either (1) a “consumer product”, which means
|
||
any tangible personal property which is normally used for personal,
|
||
family, or household purposes, or (2) anything designed or sold for
|
||
incorporation into a dwelling. In determining whether a product is
|
||
a consumer product, doubtful cases shall be resolved in favor of
|
||
coverage. For a particular product received by a particular user,
|
||
“normally used” refers to a typical or common use of that class of
|
||
product, regardless of the status of the particular user or of the
|
||
way in which the particular user actually uses, or expects or is
|
||
expected to use, the product. A product is a consumer product
|
||
regardless of whether the product has substantial commercial,
|
||
industrial or non-consumer uses, unless such uses represent the
|
||
only significant mode of use of the product.
|
||
|
||
“Installation Information” for a User Product means any methods,
|
||
procedures, authorization keys, or other information required to
|
||
install and execute modified versions of a covered work in that
|
||
User Product from a modified version of its Corresponding Source.
|
||
The information must suffice to ensure that the continued
|
||
functioning of the modified object code is in no case prevented or
|
||
interfered with solely because modification has been made.
|
||
|
||
If you convey an object code work under this section in, or with,
|
||
or specifically for use in, a User Product, and the conveying
|
||
occurs as part of a transaction in which the right of possession
|
||
and use of the User Product is transferred to the recipient in
|
||
perpetuity or for a fixed term (regardless of how the transaction
|
||
is characterized), the Corresponding Source conveyed under this
|
||
section must be accompanied by the Installation Information. But
|
||
this requirement does not apply if neither you nor any third party
|
||
retains the ability to install modified object code on the User
|
||
Product (for example, the work has been installed in ROM).
|
||
|
||
The requirement to provide Installation Information does not
|
||
include a requirement to continue to provide support service,
|
||
warranty, or updates for a work that has been modified or installed
|
||
by the recipient, or for the User Product in which it has been
|
||
modified or installed. Access to a network may be denied when the
|
||
modification itself materially and adversely affects the operation
|
||
of the network or violates the rules and protocols for
|
||
communication across the network.
|
||
|
||
Corresponding Source conveyed, and Installation Information
|
||
provided, in accord with this section must be in a format that is
|
||
publicly documented (and with an implementation available to the
|
||
public in source code form), and must require no special password
|
||
or key for unpacking, reading or copying.
|
||
|
||
7. Additional Terms.
|
||
|
||
“Additional permissions” are terms that supplement the terms of
|
||
this License by making exceptions from one or more of its
|
||
conditions. Additional permissions that are applicable to the
|
||
entire Program shall be treated as though they were included in
|
||
this License, to the extent that they are valid under applicable
|
||
law. If additional permissions apply only to part of the Program,
|
||
that part may be used separately under those permissions, but the
|
||
entire Program remains governed by this License without regard to
|
||
the additional permissions.
|
||
|
||
When you convey a copy of a covered work, you may at your option
|
||
remove any additional permissions from that copy, or from any part
|
||
of it. (Additional permissions may be written to require their own
|
||
removal in certain cases when you modify the work.) You may place
|
||
additional 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
|
||
you add to a covered work, you may (if authorized by the copyright
|
||
holders of that material) supplement the terms of this License with
|
||
terms:
|
||
|
||
a. Disclaiming warranty or limiting liability differently from
|
||
the terms of sections 15 and 16 of this License; or
|
||
|
||
b. Requiring preservation of specified reasonable legal notices
|
||
or author attributions in that material or in the Appropriate
|
||
Legal Notices displayed by works containing it; or
|
||
|
||
c. Prohibiting misrepresentation of the origin of that material,
|
||
or requiring that modified versions of such material be marked
|
||
in reasonable ways as different from the original version; or
|
||
|
||
d. Limiting the use for publicity purposes of names of licensors
|
||
or authors of the material; or
|
||
|
||
e. Declining to grant rights under trademark law for use of some
|
||
trade names, trademarks, or service marks; or
|
||
|
||
f. Requiring indemnification of licensors and authors of that
|
||
material by anyone who conveys the material (or modified
|
||
versions of it) with contractual assumptions of liability to
|
||
the recipient, for any liability that these contractual
|
||
assumptions directly impose on those licensors and authors.
|
||
|
||
All other non-permissive additional terms are considered “further
|
||
restrictions” within the meaning of section 10. If the Program as
|
||
you received it, or any part of it, contains a notice stating that
|
||
it is governed by this License along with a term that is a further
|
||
restriction, you may remove that term. If a license document
|
||
contains a further restriction but permits relicensing or conveying
|
||
under this License, you may add to a covered work material governed
|
||
by the terms of that license document, provided that the further
|
||
restriction does not survive such relicensing or conveying.
|
||
|
||
If you add terms to a covered work in accord with this section, you
|
||
must place, in the relevant source files, a statement of the
|
||
additional terms that apply to those files, or a notice indicating
|
||
where to find the applicable terms.
|
||
|
||
Additional terms, permissive or non-permissive, may be stated in
|
||
the form of a separately written license, or stated as exceptions;
|
||
the above requirements apply either way.
|
||
|
||
8. Termination.
|
||
|
||
You may not propagate or modify a covered work except as expressly
|
||
provided under this License. Any attempt otherwise to propagate or
|
||
modify it is void, and will automatically terminate your rights
|
||
under this License (including any patent licenses granted under the
|
||
third paragraph of section 11).
|
||
|
||
However, if you cease all violation of this License, then your
|
||
license from a particular copyright holder is reinstated (a)
|
||
provisionally, unless and until the copyright holder explicitly and
|
||
finally terminates your license, and (b) permanently, if the
|
||
copyright holder fails to notify you of the violation by some
|
||
reasonable means prior to 60 days after the cessation.
|
||
|
||
Moreover, your license from a particular copyright holder is
|
||
reinstated permanently if the copyright holder notifies you of the
|
||
violation by some reasonable means, this is the first time you have
|
||
received notice of violation of this License (for any work) from
|
||
that copyright holder, and you cure the violation prior to 30 days
|
||
after your receipt of the notice.
|
||
|
||
Termination of your rights under this section does not terminate
|
||
the licenses of parties who have received copies or rights from you
|
||
under this License. If your rights have been terminated and not
|
||
permanently reinstated, you do not qualify to receive new licenses
|
||
for the same material under section 10.
|
||
|
||
9. Acceptance Not Required for Having Copies.
|
||
|
||
You are not required to accept this License in order to receive or
|
||
run a copy of the Program. Ancillary propagation of a covered work
|
||
occurring solely as a consequence of using peer-to-peer
|
||
transmission to receive a copy likewise does not require
|
||
acceptance. However, nothing other than this License grants you
|
||
permission to propagate or modify any covered work. These actions
|
||
infringe copyright if you do not accept this License. Therefore,
|
||
by modifying or propagating a covered work, you indicate your
|
||
acceptance of this License to do so.
|
||
|
||
10. Automatic Licensing of Downstream Recipients.
|
||
|
||
Each time you convey a covered work, the recipient automatically
|
||
receives a license from the original licensors, to run, modify and
|
||
propagate that work, subject to this License. You are not
|
||
responsible for enforcing compliance by third parties with this
|
||
License.
|
||
|
||
An “entity transaction” is a transaction transferring control of an
|
||
organization, or substantially all assets of one, or subdividing an
|
||
organization, or merging organizations. If propagation of a
|
||
covered work results from an entity transaction, each party to that
|
||
transaction who receives a copy of the work also receives whatever
|
||
licenses to the work the party’s predecessor in interest had or
|
||
could give under the previous paragraph, plus a right to possession
|
||
of the Corresponding Source of the work from the predecessor in
|
||
interest, if the predecessor has it or can get it with reasonable
|
||
efforts.
|
||
|
||
You may not impose any further restrictions on the exercise of the
|
||
rights granted or affirmed under this License. For example, you
|
||
may not impose a license fee, royalty, or other charge for exercise
|
||
of rights granted under this License, and you may not initiate
|
||
litigation (including a cross-claim or counterclaim in a lawsuit)
|
||
alleging that any patent claim is infringed by making, using,
|
||
selling, offering for sale, or importing the Program or any portion
|
||
of it.
|
||
|
||
11. Patents.
|
||
|
||
A “contributor” is a copyright holder who authorizes use under this
|
||
License of the Program or a work on which the Program is based.
|
||
The work thus licensed is called the contributor’s “contributor
|
||
version”.
|
||
|
||
A contributor’s “essential patent claims” are all patent claims
|
||
owned or controlled by the contributor, whether already acquired or
|
||
hereafter acquired, that would be infringed by some manner,
|
||
permitted by this License, of making, using, or selling its
|
||
contributor version, but do not include claims that would be
|
||
infringed only as a consequence of further modification of the
|
||
contributor version. For purposes of this definition, “control”
|
||
includes the right to grant patent sublicenses in a manner
|
||
consistent with the requirements of this License.
|
||
|
||
Each contributor grants you a non-exclusive, worldwide,
|
||
royalty-free patent license under the contributor’s essential
|
||
patent claims, to make, use, sell, offer for sale, import and
|
||
otherwise run, modify and propagate the contents of its contributor
|
||
version.
|
||
|
||
In the following three paragraphs, a “patent license” is any
|
||
express agreement or commitment, however denominated, not to
|
||
enforce a patent (such as an express permission to practice a
|
||
patent or covenant not to sue for patent infringement). To “grant”
|
||
such a patent license to a party means to make such an agreement or
|
||
commitment not to enforce a patent 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 anyone to copy, free of charge and under the terms of this
|
||
License, through a publicly available network server or other
|
||
readily accessible means, then you must either (1) cause the
|
||
Corresponding Source to be so available, or (2) arrange to deprive
|
||
yourself of the benefit of the patent license for this particular
|
||
work, or (3) arrange, in a manner consistent with the requirements
|
||
of this License, to extend the patent license to downstream
|
||
recipients. “Knowingly relying” means you have actual knowledge
|
||
that, but for the patent license, your conveying the covered work
|
||
in a country, or your recipient’s use of the covered work in a
|
||
country, would infringe one or more identifiable patents in that
|
||
country that you have reason to believe are valid.
|
||
|
||
If, pursuant to or in connection with a single transaction or
|
||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||
covered work, and grant a patent license to some of the parties
|
||
receiving the covered work authorizing them to use, propagate,
|
||
modify or convey a specific copy of the covered work, then the
|
||
patent license you grant is automatically extended to all
|
||
recipients of the covered work and works based on it.
|
||
|
||
A patent license is “discriminatory” if it does not include within
|
||
the scope of its coverage, prohibits the exercise of, or is
|
||
conditioned on the non-exercise of one or more of the rights that
|
||
are specifically granted under this License. You may not convey a
|
||
covered work if you are a party to an arrangement with a third
|
||
party that is in the business of distributing software, under which
|
||
you make payment to the third party based on the extent of your
|
||
activity of conveying the work, and under which the third party
|
||
grants, to any of the parties who would receive the covered work
|
||
from you, a discriminatory patent license (a) in connection with
|
||
copies of the covered work conveyed by you (or copies made from
|
||
those copies), or (b) primarily for and in connection with specific
|
||
products or compilations that contain the covered work, unless you
|
||
entered into that arrangement, or that patent license was granted,
|
||
prior to 28 March 2007.
|
||
|
||
Nothing in this License shall be construed as excluding or limiting
|
||
any implied license or other defenses to infringement that may
|
||
otherwise be available to you under applicable patent law.
|
||
|
||
12. No Surrender of Others’ Freedom.
|
||
|
||
If conditions are imposed on you (whether by court order, agreement
|
||
or otherwise) that contradict the conditions of this License, they
|
||
do not excuse you from the conditions of this License. If you
|
||
cannot convey a covered work so as to satisfy simultaneously your
|
||
obligations under this License and any other pertinent obligations,
|
||
then as a consequence you may not convey it at all. For example,
|
||
if you agree to terms that obligate you to collect a royalty for
|
||
further conveying from those to whom you convey the Program, the
|
||
only way you could satisfy both those terms and this License would
|
||
be to refrain entirely from conveying the Program.
|
||
|
||
13. Use with the GNU Affero General Public License.
|
||
|
||
Notwithstanding any other provision of this License, you have
|
||
permission to link or combine any covered work with a work licensed
|
||
under version 3 of the GNU Affero General Public License into a
|
||
single combined work, and to convey the resulting work. The terms
|
||
of this License 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 the combination as such.
|
||
|
||
14. Revised Versions of this License.
|
||
|
||
The Free Software Foundation may publish revised and/or new
|
||
versions of the GNU General Public License from time to time. Such
|
||
new versions will be similar in spirit to the present version, but
|
||
may differ in detail to address new problems or concerns.
|
||
|
||
Each version is given a distinguishing version number. If the
|
||
Program specifies that a certain numbered version of the GNU
|
||
General Public License “or any later version” applies to it, you
|
||
have the option of following the terms and conditions either of
|
||
that numbered version or of any later version published by the Free
|
||
Software Foundation. If the Program does not specify a version
|
||
number of the GNU General Public License, you may choose any
|
||
version ever published by the Free Software Foundation.
|
||
|
||
If the Program specifies that a proxy can decide which future
|
||
versions of the GNU General Public License can be used, that
|
||
proxy’s public statement of acceptance of a version permanently
|
||
authorizes you to choose that version for the Program.
|
||
|
||
Later license versions may give you additional or different
|
||
permissions. However, no additional obligations are imposed on any
|
||
author or copyright holder as a result of your choosing to follow a
|
||
later version.
|
||
|
||
15. Disclaimer of Warranty.
|
||
|
||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE
|
||
COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS IS”
|
||
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
|
||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE
|
||
RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.
|
||
SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
|
||
NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||
|
||
16. Limitation of Liability.
|
||
|
||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES
|
||
AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR
|
||
DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
|
||
THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA
|
||
BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF
|
||
THE POSSIBILITY OF SUCH DAMAGES.
|
||
|
||
17. Interpretation of Sections 15 and 16.
|
||
|
||
If the disclaimer of warranty and limitation of liability provided
|
||
above cannot be given local legal effect according to their terms,
|
||
reviewing courts shall apply local law that most closely
|
||
approximates an absolute waiver of all civil liability in
|
||
connection with the Program, unless a warranty or assumption of
|
||
liability accompanies a copy 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 greatest
|
||
possible use to the public, the best way to achieve this is to make it
|
||
free software which everyone can redistribute and change under these
|
||
terms.
|
||
|
||
To do so, attach the following notices to the program. It is safest
|
||
to attach them to the start of each source file to most effectively
|
||
state the exclusion of warranty; and each file should have at least the
|
||
“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 <https://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 short
|
||
notice 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 show the
|
||
appropriate parts of the General Public License. Of course, your
|
||
program’s commands might be different; for a GUI interface, you would
|
||
use 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, see <https://www.gnu.org/licenses/>.
|
||
|
||
The GNU General Public License does not permit incorporating your
|
||
program into proprietary programs. If your program is a subroutine
|
||
library, you may consider it more useful to permit linking proprietary
|
||
applications with the library. If this is what you want to do, use the
|
||
GNU Lesser General Public License instead of this License. But first,
|
||
please read <https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||
|