m4-commit
[Top][All Lists]
Advanced

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

[SCM] GNU M4 source repository branch, branch-1.4, updated. v1.4.12-10-g


From: Eric Blake
Subject: [SCM] GNU M4 source repository branch, branch-1.4, updated. v1.4.12-10-g7553c0a
Date: Thu, 18 Dec 2008 19:20:02 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU M4 source repository".

http://git.sv.gnu.org/gitweb/?p=m4.git;a=commitdiff;h=7553c0a3e36668e0f32e816c32f8924f6e052d42

The branch, branch-1.4 has been updated
       via  7553c0a3e36668e0f32e816c32f8924f6e052d42 (commit)
       via  9eeeb515e06939d429ecfee3d8b6d5e16697d264 (commit)
       via  f3cbea82645f39ac92bc4fb04e3c72a79545740e (commit)
       via  6a7f94a6a8f5795d29caac5e927ad99a92bf695a (commit)
      from  5c3e3a62494b3b1712ea5b33e95d2917358806e2 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 7553c0a3e36668e0f32e816c32f8924f6e052d42
Author: Eric Blake <address@hidden>
Date:   Tue Nov 4 15:33:07 2008 -0700

    Document optimized forloop.
    
    * doc/m4.texinfo (Improved forloop): Mention alternate style that
    avoids define overhead.
    * examples/forloop3.m4: New file.
    * examples/Makefile.am (EXTRA_DIST): Distribute it.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 5ace13749e5afae1351d9b6035c2ba9309ac20cd)

commit 9eeeb515e06939d429ecfee3d8b6d5e16697d264
Author: Eric Blake <address@hidden>
Date:   Thu Dec 18 11:29:35 2008 -0700

    Deal with M4 1.4.x limitation on builtin tokens.
    
    * doc/m4.texinfo (Composition): Mention limitation on curry.
    (Improved copy): New node.
    * examples/stack_sep.m4: New file.
    * examples/Makefile.am (EXTRA_DIST): Distribute it.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 92f059a8d7e6e6f96e791fcc14d6dcbdba7b3b9c)

commit f3cbea82645f39ac92bc4fb04e3c72a79545740e
Author: Eric Blake <address@hidden>
Date:   Thu Dec 18 06:09:35 2008 -0700

    Document copy composite using stack_foreach and curry.
    
    * doc/m4.texinfo (Stacks): New node, to document pushdef stack
    manipulation.
    (Ifelse): Move define_blind...
    (Composition): ...to this new node.  Document currying, then use
    it to implement copy and rename.
    * examples/curry.m4: New file.
    * examples/stack.m4: Likewise.
    * examples/Makefile.am (EXTRA_DIST): Distribute them.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit cacb2125cc8d3e14dfdcc24260d2daf2a7684640)

commit 6a7f94a6a8f5795d29caac5e927ad99a92bf695a
Author: Eric Blake <address@hidden>
Date:   Sat Dec 6 10:53:22 2008 -0700

    Don't override signal handlers installed by c-stack.
    
    * src/m4.c (main): Reorder installation of signal handlers, so we
    don't trash a SIGBUS handler installed by c-stack.  Also provide a
    SIGSEGV fallback, for platforms where c-stack combined with
    libsigsegv uses something lower level than SIGSEGV.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit f66f95f60436fe3c8e805268338fbfb1087a385d)

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog             |   32 ++++
 doc/m4.texinfo        |  462 +++++++++++++++++++++++++++++++++++++++++++------
 examples/Makefile.am  |    4 +
 examples/curry.m4     |    7 +
 examples/forloop3.m4  |   13 ++
 examples/stack.m4     |   16 ++
 examples/stack_sep.m4 |   17 ++
 src/m4.c              |   10 +-
 8 files changed, 501 insertions(+), 60 deletions(-)
 create mode 100644 examples/curry.m4
 create mode 100644 examples/forloop3.m4
 create mode 100644 examples/stack.m4
 create mode 100644 examples/stack_sep.m4

diff --git a/ChangeLog b/ChangeLog
index b530098..802ee0a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,35 @@
+2008-12-18  Eric Blake  <address@hidden>
+
+       Document optimized forloop.
+       * doc/m4.texinfo (Improved forloop): Mention alternate style that
+       avoids define overhead.
+       * examples/forloop3.m4: New file.
+       * examples/Makefile.am (EXTRA_DIST): Distribute it.
+
+       Deal with M4 1.4.x limitation on builtin tokens.
+       * doc/m4.texinfo (Composition): Mention limitation on curry.
+       (Improved copy): New node.
+       * examples/stack_sep.m4: New file.
+       * examples/Makefile.am (EXTRA_DIST): Distribute it.
+
+       Document copy composite using stack_foreach and curry.
+       * doc/m4.texinfo (Stacks): New node, to document pushdef stack
+       manipulation.
+       (Ifelse): Move define_blind...
+       (Composition): ...to this new node.  Document currying, then use
+       it to implement copy and rename.
+       * examples/curry.m4: New file.
+       * examples/stack.m4: Likewise.
+       * examples/Makefile.am (EXTRA_DIST): Distribute them.
+
+2008-12-17  Eric Blake  <address@hidden>
+
+       Don't override signal handlers installed by c-stack.
+       * src/m4.c (main): Reorder installation of signal handlers, so we
+       don't trash a SIGBUS handler installed by c-stack.  Also provide a
+       SIGSEGV fallback, for platforms where c-stack combined with
+       libsigsegv uses something lower level than SIGSEGV.
+
 2008-12-12  Eric Blake  <address@hidden>
 
        Double size of temp file cache.
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index 702d498..c5bdc30 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -197,6 +197,8 @@ Conditionals, loops, and recursion
 * Shift::                       Recursion in @code{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
 
@@ -270,6 +272,7 @@ Correct version of some examples
 * Improved exch::               Solution for @code{exch}
 * Improved forloop::            Solution for @code{forloop}
 * Improved foreach::            Solution for @code{foreach}
+* Improved copy::               Solution for @code{copy}
 * Improved m4wrap::             Solution for @code{m4wrap}
 * Improved cleardivert::        Solution for @code{cleardivert}
 * Improved capitalize::         Solution for @code{capitalize}
@@ -2295,6 +2298,7 @@ traceoff(`defn', `define')
 @cindex temporary redefinition of macros
 @cindex redefinition of macros, temporary
 @cindex definition stack
address@hidden pushdef stack
 @cindex stack, macro definition
 It is possible to redefine a macro temporarily, reverting to the
 previous definition at a later time.  This is done with the builtins
@@ -2597,6 +2601,8 @@ something a number of times, or while some condition is 
true.
 * Shift::                       Recursion in @code{m4}
 * Forloop::                     Iteration by counting
 * Foreach::                     Iteration by list contents
+* Stacks::                      Working with definition stacks
+* Composition::                 Building macros with macros
 @end menu
 
 @node Ifdef
@@ -2704,67 +2710,13 @@ foo(`a', `b', `c')
 @result{}arguments:3
 @end example
 
-Since m4 is a macro language, it is even possible to write a macro that
-makes defining blind macros easier:
-
address@hidden Composite define_blind (@var{name}, @ovar{value})
-Defines @var{name} as a blind macro, such that @var{name} will expand to
address@hidden only when given explicit arguments.  @var{value} should not
-be the result of @code{defn} (@pxref{Defn}).  This macro is only
-recognized with parameters, and results in an empty string.
address@hidden deffn
-
-Defining a macro to define another macro can be a bit tricky.  We want
-to use a literal @samp{$#} in the argument to the nested @code{define}.
-However, if @samp{$} and @samp{#} are adjacent in the definition of
address@hidden, then it would be expanded as the number of
-arguments to @code{define_blind} rather than the intended number of
-arguments to @var{name}.  The solution is to pass the difficult
-characters through extra arguments to a helper macro
address@hidden
-
-As for the limitation against using @code{defn}, there are two reasons.
-If a macro was previously defined with @code{define_blind}, then it can
-safely be renamed to a new blind macro using plain @code{define}; using
address@hidden to rename it just adds another layer of
address@hidden, 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 @code{define_blind} is itself a blind macro.
-
address@hidden
-$ @kbd{m4 -d}
-define(`define_blind', `ifelse(`$#', `0', ``$0'',
-`_$0(`$1', `$2', `$'`#', `$'`0')')')
address@hidden
-define(`_define_blind', `define(`$1',
-`ifelse(`$3', `0', ``$4'', `$2')')')
address@hidden
-define_blind
address@hidden
-define_blind(`foo', `arguments were $*')
address@hidden
-foo
address@hidden
-foo(`bar')
address@hidden were bar
-define(`blah', defn(`foo'))
address@hidden
-blah
address@hidden
-blah(`a', `b')
address@hidden were a,b
-defn(`blah')
address@hidden(`$#', `0', ``$0'', `arguments were $*')
address@hidden example
+For an example of a way to make defining blind macros easier, see
address@hidden
 
 @cindex multibranches
 @cindex switch statement
 @cindex case statement
-However, @code{ifelse} can take more than four arguments.  If given more
+The macro @code{ifelse} can take more than four arguments.  If given more
 than four arguments, @code{ifelse} works like a @code{case} or @code{switch}
 statement in traditional programming languages.  If @var{string-1} and
 @var{string-2} are equal, @code{ifelse} expands into @var{equal-1}, otherwise
@@ -3417,6 +3369,264 @@ It is possible to have robust iteration with linear 
behavior and sane
 from the best elements of both of these implementations to create robust
 macros (or @pxref{Improved foreach, , Answers}).
 
address@hidden Stacks
address@hidden Working with definition stacks
+
address@hidden definition stack
address@hidden pushdef stack
address@hidden stack, macro definition
+Thanks to @code{pushdef}, manipulation of a stack is an intrinsic
+operation in @code{m4}.  Normally, only the topmost definition in a
+stack is important, but sometimes, it is desirable to manipulate the
+entire definition stack.
+
address@hidden Composite stack_foreach (@var{macro}, @var{action})
address@hidden Composite stack_foreach_lifo (@var{macro}, @var{action})
+For each of the @code{pushdef} definitions associated with @var{macro},
+invoke the macro @var{action} with a single argument of that definition.
address@hidden visits the oldest definition first, while
address@hidden visits the current definition first.
address@hidden should not modify or dereference @var{macro}.  There are a
+few special macros, such as @code{defn}, which cannot be used as the
address@hidden parameter.
address@hidden deffn
+
+A sample implementation of these macros is distributed in the file
address@hidden@value{VERSION}/@/examples/@/stack.m4}.
+
address@hidden examples
address@hidden
+$ @kbd{m4 -I examples}
+include(`stack.m4')
address@hidden
+pushdef(`a', `1')pushdef(`a', `2')pushdef(`a', `3')
address@hidden
+define(`show', ``$1'
+')
address@hidden
+stack_foreach(`a', `show')dnl
address@hidden
address@hidden
address@hidden
+stack_foreach_lifo(`a', `show')dnl
address@hidden
address@hidden
address@hidden
address@hidden example
+
+Now for the implementation.  Note the definition of a helper macro,
address@hidden, which destructively swaps the contents of one
+stack of definitions into the reverse order in the temporary macro
address@hidden  By calling the helper twice, the original order is
+restored back into the macro @samp{$1}; since the operation is
+destructive, this explains why @samp{$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
address@hidden  The choice of helper names is intentional; since @samp{-} 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 @code{defn} where
+necessary.  Finally, note that any macro used in the traversal of a
address@hidden stack, such as @code{pushdef} or @code{defn}, cannot be
+handled by @code{stack_foreach}, since the macro would temporarily be
+undefined during the algorithm.
+
address@hidden examples
address@hidden
+$ @kbd{m4 -I examples}
+undivert(`stack.m4')dnl
address@hidden(`-1')
address@hidden stack_foreach(macro, action)
address@hidden Invoke ACTION with a single argument of each definition
address@hidden from the definition stack of MACRO, starting with the oldest.
address@hidden(`stack_foreach',
address@hidden(`$1', `tmp-$1')'dnl
address@hidden(`tmp-$1', `$1', `$2(defn(`$1'))')')
address@hidden stack_foreach_lifo(macro, action)
address@hidden Invoke ACTION with a single argument of each definition
address@hidden from the definition stack of MACRO, starting with the newest.
address@hidden(`stack_foreach_lifo',
address@hidden(`$1', `tmp-$1', `$2(defn(`$1'))')'dnl
address@hidden(`tmp-$1', `$1')')
address@hidden(`_stack_reverse',
address@hidden(`$1', `pushdef(`$2', defn(`$1'))$3`'popdef(`$1')$0($@@)')')
address@hidden'dnl
address@hidden example
+
address@hidden Composition
address@hidden Building macros with macros
+
address@hidden macro composition
address@hidden composing 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.
+
address@hidden macro, blind
address@hidden blind macro
address@hidden Composite define_blind (@var{name}, @ovar{value})
+Defines @var{name} as a blind macro, such that @var{name} will expand to
address@hidden only when given explicit arguments.  @var{value} should not
+be the result of @code{defn} (@pxref{Defn}).  This macro is only
+recognized with parameters, and results in an empty string.
address@hidden deffn
+
+Defining a macro to define another macro can be a bit tricky.  We want
+to use a literal @samp{$#} in the argument to the nested @code{define}.
+However, if @samp{$} and @samp{#} are adjacent in the definition of
address@hidden, then it would be expanded as the number of
+arguments to @code{define_blind} rather than the intended number of
+arguments to @var{name}.  The solution is to pass the difficult
+characters through extra arguments to a helper macro
address@hidden  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 @code{defn}, there are two reasons.
+If a macro was previously defined with @code{define_blind}, then it can
+safely be renamed to a new blind macro using plain @code{define}; using
address@hidden to rename it just adds another layer of
address@hidden, 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 @code{define_blind} is itself a blind macro.
+
address@hidden
+$ @kbd{m4 -d}
+define(`define_blind', `ifelse(`$#', `0', ``$0'',
+`_$0(`$1', `$2', `$'`#', `$'`0')')')
address@hidden
+define(`_define_blind', `define(`$1',
+`ifelse(`$3', `0', ``$4'', `$2')')')
address@hidden
+define_blind
address@hidden
+define_blind(`foo', `arguments were $*')
address@hidden
+foo
address@hidden
+foo(`bar')
address@hidden were bar
+define(`blah', defn(`foo'))
address@hidden
+blah
address@hidden
+blah(`a', `b')
address@hidden were a,b
+defn(`blah')
address@hidden(`$#', `0', ``$0'', `arguments were $*')
address@hidden example
+
address@hidden currying arguments
address@hidden argument currying
+Another interesting composition tactic is argument @dfn{currying}, or
+factoring a macro that takes multiple arguments for use in a context
+that provides exactly one argument.
+
address@hidden Composite curry (@var{macro}, @dots{})
+Expand to a macro call that takes exactly one argument, then appends
+that argument to the original arguments and invokes @var{macro} with the
+resulting list of arguments.
address@hidden deffn
+
+A demonstration of currying makes the intent of this macro a little more
+obvious.  The macro @code{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 @code{reverse} with two arguments
+for each definition of a macro stack.  This example uses the file
address@hidden@value{VERSION}/@/examples/@/curry.m4} included in the
+distribution.
+
address@hidden examples
address@hidden
+$ @kbd{m4 -I examples}
+include(`curry.m4')include(`stack.m4')
address@hidden
+define(`reverse', `ifelse(`$#', `0', , `$#', `1', ``$1'',
+                          `reverse(shift($@@)), `$1'')')
address@hidden
+pushdef(`a', `1')pushdef(`a', `2')pushdef(`a', `3')
address@hidden
+stack_foreach(`a', `:curry(`reverse', `4')')
address@hidden:1, 4:2, 4:3, 4
+curry(`curry', `reverse', `1')(`2')(`3')
address@hidden, 2, 1
address@hidden example
+
+Now for the implementation.  Notice how @code{curry} leaves off with a
+macro name but no open parenthesis, while still in the middle of
+collecting arguments for @samp{$1}.  The macro @code{_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
address@hidden 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 @code{curry}.
+
address@hidden examples
address@hidden
+$ @kbd{m4 -I examples}
+undivert(`curry.m4')dnl
address@hidden(`-1')
address@hidden curry(macro, args)
address@hidden Expand to a macro call that takes one argument, then invoke
address@hidden macro(args, extra).
address@hidden(`curry', `$1(shift($@@,)_$0')
address@hidden(`_curry', ``$1')')
address@hidden'dnl
address@hidden example
+
+Unfortunately, with M4 1.4.x, @code{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.
+
address@hidden renaming macros
address@hidden copying macros
address@hidden macros, copying
+Putting the last few concepts together, it is possible to copy or rename
+an entire stack of macro definitions.
+
address@hidden Composite copy (@var{source}, @var{dest})
address@hidden Composite rename (@var{source}, @var{dest})
+Ensure that @var{dest} is undefined, then define it to the same stack of
+definitions currently in @var{source}.  @code{copy} leaves @var{source}
+unchanged, while @code{rename} undefines @var{source}.  There are only a
+few macros, such as @code{copy} or @code{defn}, which cannot be copied
+via this macro.
address@hidden deffn
+
+The implementation is relatively straightforward (although since it uses
address@hidden, it is unable to copy builtin macros, such as the second
+definition of @code{a} as a synonym for @code{divnum}.  See if you can
+design a version that works around this limitation, or @pxref{Improved
+copy, , Answers}).
+
address@hidden examples
address@hidden
+$ @kbd{m4 -I examples}
+include(`curry.m4')include(`stack.m4')
address@hidden
+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')
address@hidden
+copy(`a', `b')
address@hidden
+rename(`b', `c')
address@hidden
+a b c
address@hidden b 2
+popdef(`a', `c')c a
address@hidden 0
+popdef(`a', `c')a c
address@hidden 1
address@hidden example
+
 @node Debugging
 @chapter How to debug macros and input
 
@@ -7362,6 +7572,7 @@ presented here.
 * Improved exch::               Solution for @code{exch}
 * Improved forloop::            Solution for @code{forloop}
 * Improved foreach::            Solution for @code{foreach}
+* Improved copy::               Solution for @code{copy}
 * Improved m4wrap::             Solution for @code{m4wrap}
 * Improved cleardivert::        Solution for @code{cleardivert}
 * Improved capitalize::         Solution for @code{capitalize}
@@ -7469,6 +7680,58 @@ forloop2(i, 1, 5, ``ifelse('')forloop2(i, 1, 5, ``)'')
 @error{}m4:stdin:12: recursion limit of 9 exceeded, use -L<N> to change it
 @end example
 
+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
address@hidden if other arguments are needed (@pxref{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
address@hidden@value{VERSION}/@/examples/@/forloop3.m4} rearranges the
+arguments of the helper @code{_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 @code{forloop} and the new @code{forloop_arg}.
+
address@hidden examples
address@hidden
+$ @kbd{m4 -I examples}
+include(`forloop3.m4')
address@hidden
+undivert(`forloop3.m4')dnl
address@hidden(`-1')
address@hidden forloop_arg(from, to, macro) - invoke MACRO(value) for
address@hidden   each value between FROM and TO, without define overhead
address@hidden(`forloop_arg', `ifelse(eval(`($1) <= ($2)'), `1',
address@hidden  `_forloop(`$1', eval(`$2'), `$3(', `)')')')
address@hidden forloop(var, from, to, stmt) - refactored to share code
address@hidden(`forloop', `ifelse(eval(`($2) <= ($3)'), `1',
address@hidden  `pushdef(`$1')_forloop(eval(`$2'), eval(`$3'),
address@hidden    `define(`$1',', `)$4')popdef(`$1')')')
address@hidden(`_forloop',
address@hidden  `$3`$1'$4`'ifelse(`$1', `$2', `',
address@hidden    `$0(incr(`$1'), `$2', `$3', `$4')')')
address@hidden'dnl
+forloop(`i', `1', `3', ` i')
address@hidden 1 2 3
+define(`echo', `$@@')
address@hidden
+forloop_arg(`1', `3', ` echo')
address@hidden 1 2 3
+include(`curry.m4')
address@hidden
+forloop_arg(`1', `3', `curry(`pushdef', `a')')
address@hidden
+a
address@hidden
+popdef(`a')a
address@hidden
+popdef(`a')a
address@hidden
+popdef(`a')a
address@hidden
address@hidden example
+
 Of course, it is possible to make even more improvements, such as
 adding an optional step argument, or allowing iteration through
 descending sequences.  @acronym{GNU} Autoconf provides some of these
@@ -7881,6 +8144,91 @@ include(`loop.m4')dnl
 
 @end ignore
 
address@hidden Improved copy
address@hidden Solution for @code{copy}
+
+The macro @code{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 @code{curry}, where it is
+silently flattened to an empty string (@pxref{Composition}).  Rather
+than using the problematic @code{curry} to work around the limitation
+that @code{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 @code{pushdef} call sequence needed, so that we are no
+longer passing a builtin token through a text macro.
+
address@hidden Composite stack_foreach_sep (@var{macro}, @var{pre}, @var{post}, 
@
+  @var{sep})
address@hidden Composite stack_foreach_sep_lifo (@var{macro}, @var{pre}, @
+  @var{post}, @var{sep})
+For each of the @code{pushdef} definitions associated with @var{macro},
+expand the sequence @address@hidden'definition`'@var{post}}.
+Additionally, expand @var{sep} between definitions.
address@hidden visits the oldest definition first, while
address@hidden visits the current definition first.  The
+expansion may dereference @var{macro}, but should not modify it.  There
+are a few special macros, such as @code{defn}, which cannot be used as
+the @var{macro} parameter.
address@hidden deffn
+
+Note that @code{stack_foreach(address@hidden', address@hidden')} is
+equivalent to @code{stack_foreach_sep(address@hidden', address@hidden(',
+`)')}.  By supplying explicit parentheses, split among the @var{pre} and
address@hidden arguments to @code{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 @var{pre} and @var{post} empty.  The new macro also adds a
+separator that is only output after the first iteration of the helper
address@hidden, implemented by prepending the original
address@hidden to @var{pre} and omitting a @var{sep} argument in subsequent
+iterations.  As an added bonus, using @code{stack_foreach_sep} to
+implement @code{copy} performs fewer macro invocations.  The improved
+stack walking macros are available in
address@hidden@value{VERSION}/@/examples/@/stack_sep.m4}:
+
address@hidden examples
address@hidden
+$ @kbd{m4 -I examples}
+include(`stack_sep.m4')
address@hidden
+define(`copy', `ifdef(`$2', `errprint(`$2 already defined
+')m4exit(`1')',
+   `stack_foreach_sep(`$1', `pushdef(`$2',', `)')')')dnl
+pushdef(`a', `1')pushdef(`a', defn(`divnum'))
address@hidden
+copy(`a', `b')
address@hidden
+b
address@hidden
+popdef(`b')
address@hidden
+b
address@hidden
+pushdef(`c', `1')pushdef(`c', `2')
address@hidden
+stack_foreach_sep_lifo(`c', `', `', `, ')
address@hidden, 1
+undivert(`stack_sep.m4')dnl
address@hidden(`-1')
address@hidden stack_foreach_sep(macro, pre, post, sep)
address@hidden Invoke PRE`'defn`'POST with a single argument of each definition
address@hidden from the definition stack of MACRO, starting with the oldest, and
address@hidden separated by SEP between definitions.
address@hidden(`stack_foreach_sep',
address@hidden(`$1', `tmp-$1')'dnl
address@hidden(`tmp-$1', `$1', `$2`'defn(`$1')$3', `$4')')
address@hidden stack_foreach_sep_lifo(macro, pre, post, sep)
address@hidden Like stack_foreach_sep, but starting with the newest definition.
address@hidden(`stack_foreach_sep_lifo',
address@hidden(`$1', `tmp-$1', `$2`'defn(`$1')$3', `$4')'dnl
address@hidden(`tmp-$1', `$1')')
address@hidden(`_stack_reverse_sep',
address@hidden(`$1', `pushdef(`$2', defn(`$1'))$3`'popdef(`$1')$0(
address@hidden  `$1', `$2', `$4`'$3')')')
address@hidden'dnl
address@hidden example
+
 @node Improved m4wrap
 @section Solution for @code{m4wrap}
 
diff --git a/examples/Makefile.am b/examples/Makefile.am
index a65f988..d3e0a24 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -23,6 +23,7 @@ EXTRA_DIST =\
 capitalize.m4 \
 capitalize2.m4 \
 comments.m4 \
+curry.m4 \
 ddivert.m4 \
 debug.m4 \
 esyscmd.m4 \
@@ -37,6 +38,7 @@ foreachq3.m4 \
 foreachq4.m4 \
 forloop.m4 \
 forloop2.m4 \
+forloop3.m4 \
 fstab.m4 \
 hanoi.m4 \
 incl-test.m4 \
@@ -52,6 +54,8 @@ pushpop.m4 \
 quote.m4 \
 regexp.m4 \
 reverse.m4 \
+stack.m4 \
+stack_sep.m4 \
 sync-lines.m4 \
 sysv-args.m4 \
 trace.m4 \
diff --git a/examples/curry.m4 b/examples/curry.m4
new file mode 100644
index 0000000..00997c3
--- /dev/null
+++ b/examples/curry.m4
@@ -0,0 +1,7 @@
+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
diff --git a/examples/forloop3.m4 b/examples/forloop3.m4
new file mode 100644
index 0000000..98db20f
--- /dev/null
+++ b/examples/forloop3.m4
@@ -0,0 +1,13 @@
+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
diff --git a/examples/stack.m4 b/examples/stack.m4
new file mode 100644
index 0000000..c1b9833
--- /dev/null
+++ b/examples/stack.m4
@@ -0,0 +1,16 @@
+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
diff --git a/examples/stack_sep.m4 b/examples/stack_sep.m4
new file mode 100644
index 0000000..b11bc83
--- /dev/null
+++ b/examples/stack_sep.m4
@@ -0,0 +1,17 @@
+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
diff --git a/src/m4.c b/src/m4.c
index a414086..befc7a9 100644
--- a/src/m4.c
+++ b/src/m4.c
@@ -381,9 +381,10 @@ main (int argc, char *const *argv, char *const *envp)
 
   /* Stack overflow and program error handling.  Ignore failure to
      install a handler, since this is merely for improved output on
-     crash, and we should never crash ;).  */
-  if (c_stack_action (fault_handler) == 0)
-    nesting_limit = 0;
+     crash, and we should never crash ;).  We install SIGBUS and
+     SIGSEGV handlers prior to using the c-stack module; depending on
+     the platform, c-stack will then override none, SIGSEGV, or both
+     handlers.  */
   program_error_message
     = xasprintf (_("internal error detected; please report this bug to <%s>"),
                  PACKAGE_BUGREPORT);
@@ -398,10 +399,13 @@ main (int argc, char *const *argv, char *const *envp)
      to default signal behavior.  */
   act.sa_flags = SA_NODEFER | SA_RESETHAND;
   act.sa_handler = fault_handler;
+  sigaction (SIGSEGV, &act, NULL);
   sigaction (SIGABRT, &act, NULL);
   sigaction (SIGILL, &act, NULL);
   sigaction (SIGFPE, &act, NULL);
   sigaction (SIGBUS, &act, NULL);
+  if (c_stack_action (fault_handler) == 0)
+    nesting_limit = 0;
 
 #ifdef DEBUG_STKOVF
   /* Make it easier to test our fault handlers.  Exporting M4_CRASH=0


hooks/post-receive
--
GNU M4 source repository




reply via email to

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