m4-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

branch-1_4 doc improvements


From: Eric Blake
Subject: branch-1_4 doc improvements
Date: Sat, 08 Jul 2006 21:17:17 +0000

Here's another round of doc improvements.  It adds several
test cases (some from CVS head, as well as some to expose
our bugs in handling the empty string as a file name).  It also
changes the license to be the looser GNU FDL 1.2 or later,
rather than the previous verbatim only.  I have several more
improvements to make, trying to get 1.4.5 and head to look
more alike in style; but this patch was getting too big for
my likings (not to mention the testsuite currently fails, due
to some of the new tests).  I've also been starting to look
at porting branch fixes into head, expect patches in that
direction as I complete reasonable chuncks; although maybe
it would be better to get Gary's changeresyntax in first to
avoid a few conflicts.

We're now at 95 tests; if I come up with many more, I'll have
to modify the testsuite to handle 3-digit test numbers :)

2006-07-08  Eric Blake  <address@hidden>

        * checks/get-them: Make filtering easier.
        * checks/check-them: Filter non-input lines, so line counts are
        more realistic in the documentation, and so changeword tests work
        even when dnl is disabled.
        * doc/m4.texinfo: Adjust example line numbers.  Clean up
        front-matter, following autoconf's example.
        (Changeword): Enable tests, skipping if changeword not supported.
        (Define, Defn, Ifelse): Backport more examples from head.
        (Input processing, Answers): New nodes, backported from head.
        (Include): Expand test to cover empty filename.
        (Undivert): Add test of undivert(0).
Index: checks/check-them
===================================================================
RCS file: /sources/m4/m4/checks/Attic/check-them,v
retrieving revision 1.1.1.1.2.7
diff -u -p -r1.1.1.1.2.7 check-them
--- checks/check-them   3 Jul 2006 17:01:07 -0000       1.1.1.1.2.7
+++ checks/check-them   8 Jul 2006 21:09:00 -0000
@@ -41,15 +41,20 @@ fi
 # Run the tests.
 for file
 do
+  test -f "$file" || {
+    echo "No such file: $file"
+    continue
+  }
   echo "Checking $file"
-  LC_MESSAGES=C m4 -d -I "$examples" $file >$out 2>$err
+  sed -e '/^dnl @/d' -e '/^\^D$/q' "$file" \
+    | LC_MESSAGES=C m4 -d -I "$examples" - >$out 2>$err
 
   if test $? = 77 ; then
     skipped="$skipped $file"
     continue
   fi
 
-  sed -e '/^dnl @result{}/!d' -e 's///' -e "s|m4.input|$file|" $file > $xout
+  sed -e '/^dnl @result{}/!d' -e 's///' "$file" > $xout
 
   if cmp -s $out $xout; then
     :
@@ -60,8 +65,7 @@ do
     diff $xout $out
   fi
 
-  sed -e '/^dnl @error{}/!d' -e 's///' -e "s|m4.input|$file|" \
-      -e "s| m4:| $m4:|" $file > $xerr
+  sed -e '/^dnl @error{}/!d' -e 's///' -e "s| m4:| $m4:|" "$file" > $xerr
 
   if cmp -s $err $xerr; then
     :
Index: checks/get-them
===================================================================
RCS file: /sources/m4/m4/checks/Attic/get-them,v
retrieving revision 1.1.1.1.2.2
diff -u -p -r1.1.1.1.2.2 get-them
--- checks/get-them     22 Jun 2006 17:49:18 -0000      1.1.1.1.2.2
+++ checks/get-them     8 Jul 2006 21:09:00 -0000
@@ -46,7 +46,7 @@ BEGIN {
     seq++;
     count++;
     file = sprintf("%02d.%s", count, node);
-    printf("dnl %s:%d: Origin of test\n", FILENAME, NR) > file;
+    printf("dnl @ %s:%d: Origin of test\n", FILENAME, NR) > file;
     next;
   }
   if ($0 ~ /address@hidden example$/) {
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.1.1.1.2.32
diff -u -p -r1.1.1.1.2.32 m4.texinfo
--- doc/m4.texinfo      7 Jul 2006 20:30:21 -0000       1.1.1.1.2.32
+++ doc/m4.texinfo      8 Jul 2006 21:09:01 -0000
@@ -1,52 +1,71 @@
 \input texinfo @c -*-texinfo-*-
address@hidden %**start of header
address@hidden ========================================================
address@hidden %**start of header
 @setfilename m4.info
address@hidden GNU macro processor
address@hidden For double-sided printing, uncomment:
address@hidden @setchapterpage odd
address@hidden GNU M4 macro processor
address@hidden odd
address@hidden
address@hidden
address@hidden ifnothtml
 @finalout
address@hidden %**end of header
 
 @include version.texi
 
address@hidden @tabchar{}
address@hidden ----------
 @c The testsuite expects literal tab output in some examples, but
 @c literal tabs in texinfo lead to formatting issues.
 @macro tabchar
 @      @c
 @end macro
 
address@hidden GNU programming tools
address@hidden
-* m4: (m4).                     A powerful macro processor.
address@hidden direntry
address@hidden @ovar(ARG)
address@hidden -------------------
address@hidden The ARG is an optional argument.  To be used for macro arguments 
in
address@hidden their documentation.
address@hidden ovar{varname}
address@hidden@address@hidden
address@hidden macro
 
address@hidden
-This file documents GNU M4 @value{VERSION}.
address@hidden @dvar(ARG, DEFAULT)
address@hidden -------------------
address@hidden The ARG is an optional argument, defaulting to DEFAULT.  To be 
used
address@hidden for macro arguments in their documentation.
address@hidden dvar{varname, default}
address@hidden@var{\varname\} = @address@hidden
address@hidden macro
 
-Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006
-Free Software Foundation, Inc.
address@hidden %**end of header
address@hidden ========================================================
 
-Permission is granted to make and distribute verbatim copies of
-this manual provided the copyright notice and this permission notice
-are preserved on all copies.
address@hidden
 
address@hidden
-Permission is granted to process this file through TeX and print the
-results, provided the printed document carries copying permission
-notice identical to this one except for the removal of this paragraph
-(this paragraph not being relevant to the printed manual).
+This manual is for GNU M4 (version @value{VERSION}, @value{UPDATED}),
+a package containing an implementation the m4 macro language.
 
address@hidden ignore
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided that the entire
-resulting derived work is distributed under the terms of a permission
-notice identical to this one.
-
-Permission is granted to copy and distribute translations of this manual
-into another language, under the above conditions for modified versions,
-except that this permission notice may be stated in a translation approved
-by the Foundation.
address@hidden ifnottex
+Copyright @copyright{} 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005,
+2006 Free Software Foundation, Inc.
+
address@hidden
+Permission is granted to copy, distribute and/or modify this document
+under the terms of the @acronym{GNU} Free Documentation License,
+Version 1.2 or any later version published by the Free Software
+Foundation; with no Invariant Sections, with the Front-Cover texts
+being ``A @acronym{GNU} Manual,'' and with the Back-Cover Texts as in
+(a) below.  A copy of the license is included in the section entitled
address@hidden Free Documentation License.''
+
+(a) The FSF's Back-Cover Text is: ``You have freedom to copy and
+modify this @acronym{GNU} Manual, like @acronym{GNU} software.  Copies
+published by the Free Software Foundation raise funds for
address@hidden development.''
address@hidden quotation
address@hidden copying
+
address@hidden GNU programming tools
address@hidden
+* M4: (m4).                     A powerful macro processor.
address@hidden direntry
 
 @titlepage
 @title GNU M4, version @value{VERSION}
@@ -56,30 +75,17 @@ by the Foundation.
 
 @page
 @vskip 0pt plus 1filll
-Copyright @copyright{} 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005,
-2006 Free Software Foundation, Inc.
-
-Permission is granted to make and distribute verbatim copies of
-this manual provided the copyright notice and this permission notice
-are preserved on all copies.
-
-Permission is granted to copy and distribute modified versions of this
-manual under the conditions for verbatim copying, provided that the entire
-resulting derived work is distributed under the terms of a permission
-notice identical to this one.
-
-Permission is granted to copy and distribute translations of this manual
-into another language, under the above conditions for modified versions,
-except that this permission notice may be stated in a translation approved
-by the Foundation.
address@hidden
 @end titlepage
 
address@hidden
+
 @ifnottex
 @node Top, Preliminaries, (dir), (dir)
 @top GNU M4
address@hidden
address@hidden ifnottex
 
address@hidden @item @address@hidden @value{hfillkludge} (UtilD, UtilT, SrcCD)
address@hidden
 GNU @code{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
@@ -132,6 +138,7 @@ changeword will go away and you should n
 * Frozen files::                Fast loading of frozen states
 
 * Compatibility::               Compatibility with other versions of m4
+* Answers::                     Answers
 * Concept index::               Index for many concepts
 * Macro index::                 Index for all m4 macros
 
@@ -153,6 +160,7 @@ Lexical and syntactic conventions
 * Quoted strings::              Quoting input to m4
 * Other tokens::                Other kinds of input tokens
 * Comments::                    Comments in m4 input
+* Input processing::            How m4 copies input to output
 
 How to invoke macros
 
@@ -244,8 +252,6 @@ Compatibility with other versions of @co
 @end detailmenu
 @end menu
 
address@hidden ifnottex
-
 @node Preliminaries, Syntax, Top, Top
 @chapter Introduction and preliminaries
 
@@ -627,6 +633,7 @@ contain comments.
 * Quoted strings::              Quoting input to m4
 * Other tokens::                Other kinds of input tokens
 * Comments::                    Comments in m4 input
+* Input processing::            How m4 copies input to output
 @end menu
 
 @node Names, Quoted strings, Syntax, Syntax
@@ -673,7 +680,7 @@ The quote characters can be changed at a
 Any character, that is neither a part of a name, nor of a quoted string,
 is a token by itself.
 
address@hidden Comments,  , Other tokens, Syntax
address@hidden Comments
 @section Comments
 
 @cindex comments
@@ -697,6 +704,50 @@ The comment delimiters can be changed to
 the builtin macro @code{changecom}.  @xref{Changecom}, for more
 information.
 
address@hidden Input processing
address@hidden Input Processing
+
+As @code{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 @code{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.
+
address@hidden expands a macro as soon as possible.  It it finds a macro call
+when collecting the arguments to another, it will expand the second
+call first.  If the input is
+
address@hidden ignore
address@hidden
+format(`Result is %d', eval(`2**15'))
address@hidden example
+
address@hidden
address@hidden will first expand @samp{eval(2**15)} to @samp{32768}, and only
+then expand the resulting call
+
address@hidden ignore
address@hidden
+format(`Result is %d', `32768')
address@hidden example
+
address@hidden
+which will give the output
+
address@hidden ignore
address@hidden
+Result is 32768
address@hidden example
+
+The order in which @code{m4} expands the macros can be explored using
+the @ref{Trace} facilities of GNU @code{m4}.
+
+This process continues until there are no more macro calls to expand and
+all the input has been consumed.
+
 @node Macros, Definitions, Syntax, Top
 @chapter How to invoke macros
 
@@ -815,7 +866,8 @@ divert`'
 @end example
 
 @noindent
-the @code{divert} builtin macro will be called.
+the @code{divert} builtin macro will be called, which expands to the
+empty string.
 
 The output of macro evaluations is always rescanned.  The following
 example would yield the string @samp{de}, exactly as if @code{m4}
@@ -1024,7 +1076,7 @@ the output.  This can be avoided by use 
 The first argument to @code{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
-define @code{one}:
+redefine @code{one}:
 
 @example
 define(foo, one)
@@ -1035,6 +1087,32 @@ one
 @result{}two
 @end example
 
+The first argument to @code{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 recognised.  It can only be referenced by the builtins @ref{Indir}
+and @ref{Defn}.
+
address@hidden arrays
+Arrays and associative arrays can be simulated by using this trick.
+
address@hidden
+define(`array', `defn(format(``array[%d]'', `$1'))')
address@hidden
+define(`array_set', `define(format(``array[%d]'', `$1'), `$2')')
address@hidden
+array_set(`4', `array element no. 4')
address@hidden
+array_set(`17', `array element no. 17')
address@hidden
+array(`4')
address@hidden element no. 4
+array(eval(`10 + 7'))
address@hidden element no. 17
address@hidden example
+
+Change the @code{%d} to @code{%s} and it is an associative array.
+
 The macro @code{define} is recognized only with parameters.
 
 @node Arguments, Pseudo Arguments, Define, Definitions
@@ -1312,7 +1390,21 @@ bar
 @result{}This is bar
 @end example
 
-The macro @code{defn} is recognized only with parameters.
+Macros used as string variables should be referred through @code{defn},
+to avoid unwanted expansion of the text:
+
address@hidden
+define(`string', `The macro dnl is very useful
+')
address@hidden
+string
address@hidden macro @comment
+defn(`string')
address@hidden macro dnl is very useful
address@hidden
address@hidden example
+
+he macro @code{defn} is recognized only with parameters.
 
 @node Pushdef, Indir, Defn, Definitions
 @section Temporarily redefining macros
@@ -1519,7 +1611,15 @@ block comment, as an alternative to repe
 special usage is recognized by GNU @code{m4}, so that in this case, the
 warning about missing arguments is never triggered.
 
-If called with three or four arguments, @code{ifelse} expands into
address@hidden
+ifelse(`some comments')
address@hidden
+ifelse(`foo', `bar')
address@hidden:2: m4: Warning: too few arguments to builtin `ifelse'
address@hidden
address@hidden example
+
+f called with three or four arguments, @code{ifelse} expands into
 @var{equal}, if @var{string-1} and @var{string-2} are equal (character
 for character), otherwise it expands to @var{not-equal}.
 
@@ -1552,7 +1652,6 @@ foo(`a', `b', `c')
 @result{}arguments:3
 @end example
 
-
 @cindex multibranches
 However, @code{ifelse} can take more than four arguments.  If given more
 than four arguments, @code{ifelse} works like a @code{case} or @code{switch}
@@ -1599,6 +1698,8 @@ It takes any number of arguments, and ex
 argument, separated by commas, with each argument quoted.
 
 @example
+shift
address@hidden
 shift(`bar')
 @result{}
 shift(`foo', `bar', `baz')
@@ -1752,7 +1853,7 @@ f(popdef(`f')dumpdef(`f'))
 @error{}f:@tabchar{}``$0'1'
 @result{}f2
 f(popdef(`f')dumpdef(`f'))
address@hidden:7: m4: undefined macro `f'
address@hidden:3: m4: undefined macro `f'
 @result{}f1
 @end example
 
@@ -1828,7 +1929,7 @@ undefine(`foo')
 ifdef(`foo', `yes', `no')
 @result{}no
 indir(`foo')
address@hidden:17: m4: undefined macro `foo'
address@hidden:8: m4: undefined macro `foo'
 @result{}
 define(`foo', `blah')
 @result{}
@@ -2014,7 +2115,7 @@ next newline, on whatever line containin
 @example
 dnl(`this is ignored',
 `so is this') and this too
address@hidden:3: m4: Warning: excess arguments to builtin `dnl' ignored
address@hidden:2: m4: Warning: excess arguments to builtin `dnl' ignored
 but not this
 @result{}but not this
 @end example
@@ -2081,6 +2182,11 @@ There is no way in @code{m4} to quote a 
 left quote, except using @code{changequote} to change the current
 quotes.
 
+If the quotes should be changed from, say, @samp{[} to @samp{[[},
+temporary quote characters have to be defined.  To achieve this, two
+calls of @code{changequote} must be made, one for the temporary quotes
+and one for the new quotes.
+
 Neither quote string should start with a letter or @samp{_} (underscore),
 as they will be confused with names in the input.  Doing so disables
 the quoting mechanism.
@@ -2166,8 +2272,9 @@ Using @code{changeword}, you can change 
 @code{m4}'s lexical rules might be useful (for example) if you wanted to
 apply translations to a file of numbers:
 
address@hidden ignore
 @example
+ifdef(`changeword', `', `m4exit(`77')')
address@hidden
 changeword(`[_a-zA-Z0-9]+')
 @result{}
 define(`1', `0')1
@@ -2178,8 +2285,9 @@ Tightening the lexical rules is less use
 make some of the builtins unavailable.  You could use it to prevent
 accidental call of builtins, for example:
 
address@hidden ignore
 @example
+ifdef(`changeword', `', `m4exit(`77')')
address@hidden
 define(`_indir', defn(`indir'))
 @result{}
 changeword(`_[_a-zA-Z0-9]*')
@@ -2200,8 +2308,9 @@ is a restriction on the regular expressi
 supplied contains any grouped subexpressions, then text outside
 the first of these is discarded before symbol lookup.  So:
 
address@hidden ignore
 @example
+ifdef(`changeword', `', `m4exit(`77')')
address@hidden
 changecom(`/*', `*/')dnl
 define(`foo', `bar')dnl
 changeword(`#\([_a-zA-Z0-9]*\)')
@@ -2234,8 +2343,9 @@ First, the @TeX{} version:
 @noindent
 Then, the @code{m4} version:
 
address@hidden ignore
 @example
+ifdef(`changeword', `', `m4exit(`77')')
address@hidden
 define(`a', `errprint(`Hello')')dnl
 changeword(`@@\([_a-zA-Z0-9]*\)')
 @result{}
@@ -2360,14 +2470,19 @@ contents of @var{filename}.
 It is an error for an @code{include}d file not to exist.  If you do
 not want error messages about non-existent files, @code{sinclude} can
 be used to include a file, if it exists, expanding to nothing if it
-does not.
+does not.  The empty string counts as a file that does not exist.
 
 @example
 include(`none')
 @result{}
address@hidden:2: m4: cannot open `none': No such file or directory
address@hidden:1: m4: cannot open `none': No such file or directory
+include()
address@hidden
address@hidden:2: m4: cannot open `': No such file or directory
 sinclude(`none')
 @result{}
+sinclude()
address@hidden
 @end example
 
 The rest of this section assumes that @code{m4} is invoked with the
@@ -2569,7 +2684,21 @@ following @code{undivert}, the other fro
 
 When diverted text is undiverted, it is @emph{not} reread by @code{m4},
 but rather copied directly to the current output, and it is therefore
-not an error to undivert into a diversion.
+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.
+
address@hidden
+divert(`1')diverted text
+divert
address@hidden
+undivert()
address@hidden
+undivert(`0')
address@hidden
+undivert
address@hidden text
address@hidden example
 
 When a diversion has been undiverted, the diverted text is discarded,
 and it is not possible to bring back diverted text more than once.
@@ -2688,7 +2817,7 @@ define(`cleardivert',
 
 It is called just like @code{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.)
+should try to see if you can find it and correct it.  @xref{Answers}.)
 
 @node Text handling, Arithmetic, Diversions, Top
 @chapter Macros for text handling
@@ -3152,7 +3281,7 @@ square(square(`5')`+1')
 define(`foo', `666')
 @result{}
 eval(`foo/6')
address@hidden:14: m4: bad expression in eval: foo/6
address@hidden:7: m4: bad expression in eval: foo/6
 @result{}
 eval(foo/6)
 @result{}111
@@ -3555,7 +3684,7 @@ current input line number in that file.
 @example
 errprint(`m4:'__file__:__line__: `input error
 ')
address@hidden:m4.input:2: input error
address@hidden:stdin:1: input error
 @result{}
 @end example
 
@@ -3578,11 +3707,11 @@ which causes @code{m4} to exit, with exi
 
 @example
 define(`fatal_error',
-       `errprint(`m4: '__file__: __line__`: fatal error: $*
+       `errprint(`m4:'__file__:__line__`: fatal error: $*
 ')m4exit(`1')')
 @result{}
 fatal_error(`this is a BAD one, buster')
address@hidden: m4.input: 6: fatal error: this is a BAD one, buster
address@hidden:stdin:4: fatal error: this is a BAD one, buster
 @end example
 
 After this macro call, @code{m4} will exit with exit code 1.  This macro
@@ -3701,7 +3830,7 @@ It is looked up the same way as an @code
 Path}).
 
 Frozen files are sharable across architectures.  It is safe to write
-a frozen file one one machine and read it on another, given that the
+a frozen file one machine and read it on another, given that the
 second machine uses the same, or a newer version of GNU @code{m4}.
 These are simple (editable) text files, made up of directives,
 each starting with a capital letter and ending with a newline
@@ -3749,7 +3878,7 @@ at reload time, however this may not be 
 
 @end table
 
address@hidden Compatibility, Concept index, Frozen files, Top
address@hidden Compatibility
 @chapter Compatibility with other versions of @code{m4}
 
 @cindex compatibility
@@ -4018,13 +4147,50 @@ ifelse(defn(address@hidden'), address@hidden
 
 @noindent
 In cases like this one, an interdiction for a macro to hold its own
-name would be a useless limitation.  Of course, this leave more rope
+name would be a useless limitation.  Of course, this leaves more rope
 for the GNU @code{m4} user to hang himself!  Rescanning hangs may be
 avoided through careful programming, a little like for endless loops
 in traditional programming languages.
 @end itemize
 
address@hidden Concept index, Macro index, Compatibility, Top
address@hidden Answers
address@hidden Answers
+
+Some of the examples in this manuals are buggy, for demonstration
+purposes.  Correctly working macros are presented here.
+
+The @code{cleardivert} macro (@pxref{Cleardiv}) 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:
+
address@hidden
+define(`cleardivert',
+  `pushdef(`_n', divnum)divert(`-1')undivert($@@)divert(_n)popdef(`_n')')
address@hidden
+divert(`1')one
+divert
address@hidden
+cleardivert
address@hidden
+undivert
address@hidden
address@hidden
+define(`cleardivert',
+  `pushdef(`_num', divnum)divert(`-1')ifelse(`$#', `0',
+    `undivert`'', `undivert($@@)')divert(_num)popdef(`_num')')
address@hidden
+divert(`2')two
+divert
address@hidden
+cleardivert
address@hidden
+undivert
address@hidden
address@hidden example
+
address@hidden Concept index
 @unnumbered Concept index
 
 @printindex cp
@@ -4042,8 +4208,6 @@ characters removed in the index.
 
 @printindex fn
 
address@hidden
address@hidden
 @bye
 
 @c Local Variables:

reply via email to

[Prev in Thread] Current Thread [Next in Thread]