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.11-34-g


From: Eric Blake
Subject: [SCM] GNU M4 source repository branch, branch-1.4, updated. v1.4.11-34-g9ecd0ad
Date: Thu, 07 Aug 2008 13:37:26 +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=9ecd0adb27f532b798618730bbdccc336554a0fd

The branch, branch-1.4 has been updated
       via  9ecd0adb27f532b798618730bbdccc336554a0fd (commit)
       via  6864b6fd4ba383ea5aee1d35af546adad3a66e00 (commit)
       via  aacc94442bf496f95384d09cc96cde2de85c52f3 (commit)
       via  4b9952e6f4b402f518d566f9cdfe16bed6070bd3 (commit)
       via  c37fc1861252f510862c66d3d34cd18ef2a4d5c3 (commit)
       via  de17d80f8c3d1a8092c300c9f2d10bbcdf32c690 (commit)
       via  9153f733ecb71becc8cc8db3d38887ae514a8d56 (commit)
       via  b9ec07d5798eef41d68c4fa29d4fb9349f7c619d (commit)
       via  07eba241aeaf090c0f2e8248ee8a6fe65d84795c (commit)
       via  08dd3b21edf93970010ccc1b13755aeb923cd992 (commit)
       via  9efade6736703df72089915a410a94e115be0308 (commit)
       via  63e646cec4a624a6b2c0c6bd9d96f8fff4ee6382 (commit)
       via  37222eaca4a7da424ca69d2013b40ef7e9492f98 (commit)
       via  22fa1d09ac5d2e180d7d6fd1a23ca064516786af (commit)
       via  0b80d584504440ddd02ea87e0c7a9142467d6d83 (commit)
       via  a80963c774a52a3ed5e121105e653263c96c6be4 (commit)
       via  642c2a905e6979de747b9fa21a8f553a5885e7ae (commit)
       via  3862237f3e40fae508984ad27fb2bb294e11a436 (commit)
       via  d5a907320c0ef81670caaac3f82a01bae298ffc1 (commit)
       via  c52fae5f76dd2b2b54afcf37c61d8f75ff80c7be (commit)
       via  72f52d343f748b5ed1d35f47f22970ef667b03f7 (commit)
       via  028ad7d2219f899ca0526d3220aae4dc80ff4416 (commit)
       via  83eef78faf16a74f882e00495bfdcea4cbf60111 (commit)
       via  a93dd25898cb02b36c0d322bb363f701571ee5ac (commit)
       via  f0e48f03710d0605b8da3f0d80c247db12363cea (commit)
       via  6f010f29e53aaf75fd126736a15fa983dd08497f (commit)
       via  55a3e14af0078a0ab2cdeb4df837e01f98e8a5ff (commit)
       via  0aaeff55269e3e4d40c019a02f6d0fda242d356b (commit)
       via  fc6be7199b9e86d280570c8dfae4f43452f50a0f (commit)
       via  4cfbc097ec1951acb8c38c09d6124733e875c75b (commit)
       via  10b70abeb80ffe351019c5bcf807993bb68ea6da (commit)
       via  f5205f5af743b4533fc2364e321e4134e6f5a3d7 (commit)
       via  7068771434e7ffec62bf674b69f06177bbfc34d4 (commit)
       via  22598a89aca89a390cfdc8fb5cca3bfbc1c380ef (commit)
      from  a62ec6b647bb3e7105cfa625d9cb48c7297ee9d8 (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 9ecd0adb27f532b798618730bbdccc336554a0fd
Merge: 08dd3b21edf93970010ccc1b13755aeb923cd992 
6864b6fd4ba383ea5aee1d35af546adad3a66e00
Author: Eric Blake <address@hidden>
Date:   Thu Aug 7 07:19:05 2008 -0600

    Merge branch 'stackovf'
    
    Signed-off-by: Eric Blake <address@hidden>

commit 6864b6fd4ba383ea5aee1d35af546adad3a66e00
Author: Eric Blake <address@hidden>
Date:   Sun Aug 3 14:34:31 2008 -0600

    Increase ulimit stack value to be larger than SIGSTKSZ.
    
    * checks/stackovf.test (tmpfile): Use 300K rather than 50K, since
    at least OpenBSD's sh died early from an undersized stack limit.
    
    Signed-off-by: Eric Blake <address@hidden>

commit aacc94442bf496f95384d09cc96cde2de85c52f3
Author: Eric Blake <address@hidden>
Date:   Thu Jul 17 16:54:43 2008 -0600

    Fix missing copyright notices.
    
    * acinclude.m4: Add copyright license details.
    * c-boxes.el: Likewise.
    * checks/get-them: Likewise.
    * checks/check-them: Likewise.
    
    Signed-off-by: Eric Blake <address@hidden>

commit 4b9952e6f4b402f518d566f9cdfe16bed6070bd3
Author: Eric Blake <address@hidden>
Date:   Thu Jul 17 16:49:57 2008 -0600

    Remove redundant examples/stackovf.sh.
    
    * examples/stackovf.sh: Delete, now that checks has better
    version.
    * examples/Makefile.am (EXTRA_DIST): Don't distribute it.
    
    Signed-off-by: Eric Blake <address@hidden>

commit c37fc1861252f510862c66d3d34cd18ef2a4d5c3
Author: Eric Blake <address@hidden>
Date:   Thu Jul 17 12:00:49 2008 -0600

    Adjust to c-stack changes in gnulib.
    
    * src/Makefile.am (m4_LDADD): Use libsigsegv when available and
    necessary, via LIBCSTACK.
    * src/m4.c (main) [DEBUG_STACKOVF]: Make it easier to test fault
    handlers.
    * checks/stackovf.test: New file.
    * checks/Makefile.in (CHECKS): Add stackovf.test, and factor...
    (DOC_CHECKS): ...generated documentation tests into new macro.
    (DISTFILES): Distribute stackovf.test.
    * checks/check-them: Special-case stackovf.test.
    * NEWS: Enhance the NEWS item for -L improvements.
    * README: Mention the optional dependency.
    * HACKING: Mention maintenance burden added by libsigsegv.
    
    Signed-off-by: Eric Blake <address@hidden>

commit de17d80f8c3d1a8092c300c9f2d10bbcdf32c690
Author: Eric Blake <address@hidden>
Date:   Sat Jun 21 15:00:14 2008 -0600

    Use new sigaction module.
    
    * m4/gnulib-cache.m4: Import sigaction module.
    * src/m4.c (main): Drop signal() calls.
    
    Signed-off-by: Eric Blake <address@hidden>

commit 9153f733ecb71becc8cc8db3d38887ae514a8d56
Author: Eric Blake <address@hidden>
Date:   Wed Jun 18 11:38:30 2008 -0600

    Also trap SIGILL, SIGFPE, SIGBUS.
    
    * m4/gnulib-cache.m4: Import strsignal module.
    * src/m4.c (main): Register more handlers, and prefer sigaction
    when available.
    (SIGBUS, NSIG): Provide fallback when lacking.
    (signal_message): New variable, to keep async-safety.
    (fault_handler): Display faulting signal description.
    * configure.ac (gl_DISABLE_THREADS): Request gnulib modules to
    optimize for single-threaded operation.
    
    Signed-off-by: Eric Blake <address@hidden>

commit b9ec07d5798eef41d68c4fa29d4fb9349f7c619d
Author: Eric Blake <address@hidden>
Date:   Fri Jun 6 16:37:21 2008 -0600

    Inform users what to do in case of programmer error.
    
    * src/m4.h (EXIT_INTERNAL_ERROR): New macro.
    * configure.ac (AC_TYPE_SIGNAL): Delete, now that we assume C89.
    * src/m4.c (fault_handler): New method.
    (program_error_message): New variable, for async-safety.
    (main): Print bug reporting address rather than dump core on any
    failed assertions or detected non-stack-overflow faults.
    
    Signed-off-by: Eric Blake <address@hidden>

commit 07eba241aeaf090c0f2e8248ee8a6fe65d84795c
Author: Eric Blake <address@hidden>
Date:   Thu Jun 5 07:08:58 2008 -0600

    Replace stackovf with gnulib c-stack.
    
    * m4/gnulib.cache.m4: Import c-stack module.
    * configure.ac (AC_CHECK_HEADERS_ONCE): Remove check for
    siginfo.h, sys/wait.h.
    (AC_CHECK_TYPES): Likewise for siginfo_t.
    (AC_CHECK_MEMBERS): Likewise for sa_sigaction, ss_sp.
    (AC_CHECK_FUNCS_ONCE): Likewise for sigaction, sigaltstack,
    sigstack, sigvec, strerror.
    (M4_cv_use_stackovf): Likewise for stack overflow detection.
    * src/Makefile.am (m4_SOURCES): Don't build stackovf.c.
    * src/stackovf.c: Delete.
    * src/m4.h (setup_stackovf_trap): Delete.
    * src/m4.c (stackovf_handler): Delete.
    (main): Use c_stack_action instead of setup_stackovf_trap.  If
    stack overflow is detectable, don't limit -L artificially.
    (usage): Document unlimited default on supported systems.
    * doc/m4.texinfo (Limits control): Document new default nesting
    limit.
    * NEWS: Document this change.
    
    Signed-off-by: Eric Blake <address@hidden>

commit 08dd3b21edf93970010ccc1b13755aeb923cd992
Author: Eric Blake <address@hidden>
Date:   Wed Jul 30 07:08:29 2008 -0600

    Avoid regressions in trace and comment output.
    
    * doc/m4.texinfo (Trace): Add test.
    (Comments): Likewise.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit c9d53ab9bcef0cb04d59f5797e6f20159150b75d)
    (cherry picked from commit 0d6fb01e76bc35550a00cbf7710d1471db9e7b00)

commit 9efade6736703df72089915a410a94e115be0308
Author: Eric Blake <address@hidden>
Date:   Mon Jul 28 16:17:04 2008 -0600

    Optimize iteration examples.
    
    * examples/forloop2.m4: Avoid excess indir, by passing current
    counter value as parameter.
    * examples/foreachq3.m4: Avoid unneeded ifelse, by injecting an
    ignored argument.
    * doc/m4.texinfo (Improved forloop, Improved foreach): Update the
    documentation to match.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 12a62477d77990112a98d3c785818f17d7b5a392)

commit 63e646cec4a624a6b2c0c6bd9d96f8fff4ee6382
Author: Eric Blake <address@hidden>
Date:   Sat Jul 26 15:39:48 2008 -0600

    Give example for O(n) foreach on m4 1.4.x.
    
    * examples/foreachq4.m4: New file.
    * examples/Makefile.am (EXTRA_DIST): Distribute it.
    * doc/m4.texinfo (Improved foreach): Document linear foreach with
    m4 1.4.5 and greater.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit eeaceb311464f6d88d2782ed8773c01d49f83aba)

commit 37222eaca4a7da424ca69d2013b40ef7e9492f98
Author: Eric Blake <address@hidden>
Date:   Thu Jul 17 16:57:19 2008 -0600

    Fix missing copyright notices.
    
    * acinclude.m4: Add copyright license details.
    * c-boxes.el: Likewise.
    * checks/get-them: Likewise.
    * checks/check-them: Likewise.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 332d15af03aec4384156f2fdf9245d71c0960105)
    (cherry picked from commit e992320ec9cd96ad491309b421e9dcdaeff09971)

commit 22fa1d09ac5d2e180d7d6fd1a23ca064516786af
Author: Eric Blake <address@hidden>
Date:   Mon Jul 14 06:17:50 2008 -0600

    Add -g/--gnu command line argument.
    
    * src/m4.c (usage): Mention the new option.
    (long_options, OPTSTRING): Add new option.
    (main): Use it.
    * NEWS: Document this addition.
    * doc/m4.texinfo (Limits control): Likewise.
    (Incompatibilities): Mention future use of POSIXLY_CORRECT.
    * THANKS: Update.
    Reported by Joel E. Denny.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 8e6cc3c04610603437d9f67e337d0abf113eb46b)

commit 0b80d584504440ddd02ea87e0c7a9142467d6d83
Author: Eric Blake <address@hidden>
Date:   Fri Jul 11 07:31:24 2008 -0600

    Avoid bogus whitespace in @ovar, @dvar.
    
    * doc/m4.texinfo (ovar, dvar): Add @c.
    Based on patch by Ralf Wildenhues to Autoconf manual.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit f7c6570e3eb5596ab59b014ea83a5114866eb879)

commit a80963c774a52a3ed5e121105e653263c96c6be4
Author: Eric Blake <address@hidden>
Date:   Mon Jun 16 07:00:59 2008 -0600

    Add missing const qualifications.
    
    * src/builtin.c (builtin_tab): Declare array elements as const.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 2319d2628b8a6257622caa7d136d88021eaf8883)

commit 642c2a905e6979de747b9fa21a8f553a5885e7ae
Author: Eric Blake <address@hidden>
Date:   Tue Jun 3 06:42:14 2008 -0600

    Use progname module rather than rolling our own program_name.
    
    * m4/gnulib-cache.m4: Import progname module.
    * src/m4.c (program_name): Replace...
    (main): ...with a call to set_program_name.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 3be468475e78fc79f2e4aa60585daf7232e5c68d)

commit 3862237f3e40fae508984ad27fb2bb294e11a436
Author: Eric Blake <address@hidden>
Date:   Mon Jun 2 06:09:33 2008 -0600

    Allow autobuild usage.
    
    * m4/gnulib.cache: Import autobuild module.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit b9a0d949a0485213215c59b6df9283d4886d5fff)
    (cherry picked from commit 733d83936c8f255e6e474a5534522daf30236837)

commit d5a907320c0ef81670caaac3f82a01bae298ffc1
Author: Eric Blake <address@hidden>
Date:   Fri May 23 06:27:16 2008 -0600

    Make closing files be consistent.
    
    * src/freeze.c (reload_frozen_state): Use close_stream.
    Reported by Jean-Charles Longuet.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit f2c5adaeeca0975529d4aa782db0a9b8852818ec)

commit c52fae5f76dd2b2b54afcf37c61d8f75ff80c7be
Author: Eric Blake <address@hidden>
Date:   Wed May 21 21:49:54 2008 -0600

    Don't allow failure to freeze give exit status of 0.
    
    * src/freeze.c (produce_frozen_state): Guarantee non-zero exit on
    fopen failure.
    * doc/m4.texinfo (Using frozen files): Test the fix.
    * THANKS: Update.
    Reported by Jean-Charles Longuet.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit fba265c02ea43d6eb835b0fb27e7e2fa05834cbb)

commit 72f52d343f748b5ed1d35f47f22970ef667b03f7
Author: Eric Blake <address@hidden>
Date:   Fri May 9 09:24:41 2008 -0600

    Improve error message when frozen file is invalid.
    
    * src/freeze.c (reload_frozen_state): Track current line.
    [GET_STRING]: New helper macro.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 34985ceaf524a511894776fe446279b5a7c12ced)

commit 028ad7d2219f899ca0526d3220aae4dc80ff4416
Author: Eric Blake <address@hidden>
Date:   Fri May 9 07:59:51 2008 -0600

    Detect integer overflow when loading frozen file.
    
    * src/m4.h (includes): Add limits.h.
    (_): Define as a no-op placeholder for now.
    * src/freeze.c (reload_frozen_state) [GET_NUMBER]: Rewrite to fail
    immediately on overflow.
    Reported by Jim Meyering.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit b5fe50a4ef3e20912ee835888c9effda8a290721)

commit 83eef78faf16a74f882e00495bfdcea4cbf60111
Author: Eric Blake <address@hidden>
Date:   Wed May 7 10:55:33 2008 -0600

    Fix traceon regression introduced 2006-06-06.
    
    * src/builtin.m4 (traceon): Only perform insertion if lookup
    fails.
    * doc/m4.texinfo (Trace): Test for the bug.
    * NEWS: Document it.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit c8a2c296df00c2e8b1b3b0372cea10d0d0a0b621)

commit a93dd25898cb02b36c0d322bb363f701571ee5ac
Author: Eric Blake <address@hidden>
Date:   Sat May 3 11:51:55 2008 -0600

    Document define_blind.
    
    * doc/m4.texinfo (Ifelse): Add a new composite macro.
    * THANKS: Update.
    Suggested by Mike R.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 26b3c17ceb4f4155ff5dd13bcd9cc63039b3f242)

commit f0e48f03710d0605b8da3f0d80c247db12363cea
Author: Eric Blake <address@hidden>
Date:   Thu Apr 24 16:27:16 2008 -0600

    Add debugmode test.
    
    * doc/m4.texinfo (Debug Levels): Test -di behavior.
    (Changeword, Location): Correct examples.
    * checks/check-them (examples): Update to account for recommended
    location for running tests.
    * doc/m4.texinfo (Debug Levels): Test this behavior.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit f87a1e3fe98dd9bf9c746f24a0e8d18958c693e3)

commit 6f010f29e53aaf75fd126736a15fa983dd08497f
Author: Eric Blake <address@hidden>
Date:   Mon Apr 21 16:27:01 2008 -0600

    Fix spelling of attribution to Christopher Strachey.
    
    * doc/m4.texinfo (History, Inhibiting Invocation): Fix typo.
    * THANKS: Update.
    Reported by Fernando Carrijo.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 05528e98e0257bcccbb5001b8ff09293e42d19b6)

commit 55a3e14af0078a0ab2cdeb4df837e01f98e8a5ff
Author: Eric Blake <address@hidden>
Date:   Thu Apr 17 06:50:34 2008 -0600

    Fix buildbot failure.
    
    * doc/m4.texinfo (Diversions): Consume all of m4's output, in case
    SIGPIPE is ignored.
    * THANKS: Update.
    Detected by Bob Proulx's buildbot.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 2b570fc0192b1a07ba77bed07d582a3dd788ab7f)

commit 0aaeff55269e3e4d40c019a02f6d0fda242d356b
Author: Eric Blake <address@hidden>
Date:   Thu Apr 17 06:46:35 2008 -0600

    Avoid gcc shadowing warnings.
    
    * src/builtin.c (m4_format): s/format/expand_format, so local
    variables can be named format.
    * src/format.c (format): Rename...
    (expand_format): ...to this, and avoid the name index.
    * src/input.c (push_file): Avoid the name close.
    * src/m4.h (expand_format): Adjust prototype.
    * src/output.c (threshold_diversion_CB): Avoid the name div.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 2f26b686720395695edf10b6c81eee5bd79700e9)

commit fc6be7199b9e86d280570c8dfae4f43452f50a0f
Author: Eric Blake <address@hidden>
Date:   Tue Apr 15 14:27:54 2008 -0600

    Another 'make installcheck' fix.
    
    * doc/m4.texinfo (Diversions): s/m4/__program__/ in case
    --program-prefix was active.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 14840bcf0e8fd964aaec8459441d8b5d5b791624)

commit 4cfbc097ec1951acb8c38c09d6124733e875c75b
Author: Eric Blake <address@hidden>
Date:   Fri Apr 11 16:16:45 2008 -0600

    Ensure --program-prefix doesn't regress.
    
    * Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Enforce change from
    2008-03-10 by testing it at 'make distcheck' time.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit fb04a26fa6ac38cbe5517372b1a984af0c851876)

commit 10b70abeb80ffe351019c5bcf807993bb68ea6da
Author: Eric Blake <address@hidden>
Date:   Fri Apr 11 09:53:29 2008 -0600

    Improve OS/2+emx build.
    
    * src/m4.h [__EMX__]: OS/2 does not have a Unix-compatible
    system(3), no matter what other macros it pre-defined.
    * doc/m4.texinfo (Mkstemp): Rework test to avoid globbing failure
    on OS/2.
    * src/builtin.c (predefined_tab): Ensure all possible system
    identifiers are defined, not just the first; the testsuite will
    catch if multiple identifiers mistakenly made it through.
    * THANKS: Update.
    Reported by Elbert Pol.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 7541b497e801dc872e8034cddba77c5fa29b110f)

commit f5205f5af743b4533fc2364e321e4134e6f5a3d7
Author: Eric Blake <address@hidden>
Date:   Wed Apr 9 07:26:31 2008 -0600

    Mention how to do Free Software Directory update.
    
    * HACKING: Add another release process step.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit be555668bce19f6a52f2c664bee473001943a926)

commit 7068771434e7ffec62bf674b69f06177bbfc34d4
Author: Eric Blake <address@hidden>
Date:   Wed Apr 9 07:06:15 2008 -0600

    Remove redundant configure macros.
    
    * configure.ac (AC_CANONICAL_BUILD, AC_CANONICAL_HOST)
    (AC_SYS_LARGEFILE, AC_TYPE_SIZE_T): Delete, since gnulib does
    this.
    (AC_CHECK_HEADERS_ONCE): Remove limits.h.
    
    Signed-off-by: Eric Blake <address@hidden>
    (cherry picked from commit 2c634e429edec76605a4e7dcb3d950d2adf06e8d)

commit 22598a89aca89a390cfdc8fb5cca3bfbc1c380ef
Author: Bruno Haible <address@hidden>
Date:   Fri Apr 4 06:15:34 2008 +0200

    Run m4 tests prior to gnulib unit tests.
    
    * Makefile.am (SUBDIRS): Swap order of directories.

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

Summary of changes:
 ChangeLog             |  272 +++++++++++++++++++++++++++++++
 HACKING               |   12 ++
 Makefile.am           |    6 +-
 NEWS                  |   29 ++++
 README                |    9 +
 THANKS                |    6 +
 acinclude.m4          |    6 +-
 c-boxes.el            |   17 ++-
 checks/Makefile.in    |   12 +-
 checks/check-them     |   33 ++++-
 checks/get-them       |   18 ++-
 checks/stackovf.test  |   99 ++++++++++++
 configure.ac          |   65 +--------
 doc/m4.texinfo        |  415 +++++++++++++++++++++++++++++++++++++++++++------
 examples/Makefile.am  |    2 +-
 examples/foreachq3.m4 |   11 +-
 examples/foreachq4.m4 |   13 ++
 examples/forloop2.m4  |    8 +-
 examples/loop.m4      |    5 +-
 examples/stackovf.sh  |   83 ----------
 m4/gnulib-cache.m4    |   47 ++++++-
 src/Makefile.am       |    5 +-
 src/builtin.c         |   21 ++-
 src/format.c          |    2 +-
 src/freeze.c          |  116 ++++++++------
 src/input.c           |   12 +-
 src/m4.c              |  126 ++++++++++++---
 src/m4.h              |   14 +-
 src/output.c          |    4 +-
 src/stackovf.c        |  422 -------------------------------------------------
 30 files changed, 1146 insertions(+), 744 deletions(-)
 create mode 100755 checks/stackovf.test
 create mode 100644 examples/foreachq4.m4
 delete mode 100644 examples/stackovf.sh
 delete mode 100644 src/stackovf.c

diff --git a/ChangeLog b/ChangeLog
index 04dc8fc..7d1c5f3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,275 @@
+2008-08-03  Eric Blake  <address@hidden>
+
+       Increase ulimit stack value to be larger than SIGSTKSZ.
+       * checks/stackovf.test (tmpfile): Use 300K rather than 50K, since
+       at least OpenBSD's sh died early from an undersized stack limit.
+
+2008-07-17  Eric Blake  <address@hidden>
+
+       Fix missing copyright notices.
+       * acinclude.m4: Add copyright license details.
+       * c-boxes.el: Likewise.
+       * checks/get-them: Likewise.
+       * checks/check-them: Likewise.
+
+2008-07-17  Eric Blake  <address@hidden>
+
+       Remove redundant examples/stackovf.sh.
+       * examples/stackovf.sh: Delete, now that checks has better
+       version.
+       * examples/Makefile.am (EXTRA_DIST): Don't distribute it.
+
+2008-07-17  Eric Blake  <address@hidden>
+
+       Adjust to c-stack changes in gnulib.
+       * src/Makefile.am (m4_LDADD): Use libsigsegv when available and
+       necessary, via LIBCSTACK.
+       * src/m4.c (main) [DEBUG_STACKOVF]: Make it easier to test fault
+       handlers.
+       * checks/stackovf.test: New file.
+       * checks/Makefile.in (CHECKS): Add stackovf.test, and factor...
+       (DOC_CHECKS): ...generated documentation tests into new macro.
+       (DISTFILES): Distribute stackovf.test.
+       * checks/check-them: Special-case stackovf.test.
+       * NEWS: Enhance the NEWS item for -L improvements.
+       * README: Mention the optional dependency.
+       * HACKING: Mention maintenance burden added by libsigsegv.
+
+2008-06-21  Eric Blake  <address@hidden>
+
+       Use new sigaction module.
+       * m4/gnulib-cache.m4: Import sigaction module.
+       * src/m4.c (main): Drop signal() calls.
+
+2008-06-18  Eric Blake  <address@hidden>
+
+       Also trap SIGILL, SIGFPE, SIGBUS.
+       * m4/gnulib-cache.m4: Import strsignal module.
+       * src/m4.c (main): Register more handlers, and prefer sigaction
+       when available.
+       (SIGBUS, NSIG): Provide fallback when lacking.
+       (signal_message): New variable, to keep async-safety.
+       (fault_handler): Display faulting signal description.
+       * configure.ac (gl_DISABLE_THREADS): Request gnulib modules to
+       optimize for single-threaded operation.
+
+2008-06-06  Eric Blake  <address@hidden>
+
+       Inform users what to do in case of programmer error.
+       * src/m4.h (EXIT_INTERNAL_ERROR): New macro.
+       * configure.ac (AC_TYPE_SIGNAL): Delete, now that we assume C89.
+       * src/m4.c (fault_handler): New method.
+       (program_error_message): New variable, for async-safety.
+       (main): Print bug reporting address rather than dump core on any
+       failed assertions or detected non-stack-overflow faults.
+
+2008-06-06  Eric Blake  <address@hidden>
+
+       Replace stackovf with gnulib c-stack.
+       * m4/gnulib.cache.m4: Import c-stack module.
+       * configure.ac (AC_CHECK_HEADERS_ONCE): Remove check for
+       siginfo.h, sys/wait.h.
+       (AC_CHECK_TYPES): Likewise for siginfo_t.
+       (AC_CHECK_MEMBERS): Likewise for sa_sigaction, ss_sp.
+       (AC_CHECK_FUNCS_ONCE): Likewise for sigaction, sigaltstack,
+       sigstack, sigvec, strerror.
+       (M4_cv_use_stackovf): Likewise for stack overflow detection.
+       * src/Makefile.am (m4_SOURCES): Don't build stackovf.c.
+       * src/stackovf.c: Delete.
+       * src/m4.h (setup_stackovf_trap): Delete.
+       * src/m4.c (stackovf_handler): Delete.
+       (main): Use c_stack_action instead of setup_stackovf_trap.  If
+       stack overflow is detectable, don't limit -L artificially.
+       (usage): Document unlimited default on supported systems.
+       * doc/m4.texinfo (Limits control): Document new default nesting
+       limit.
+       * NEWS: Document this change.
+
+2008-07-30  Eric Blake  <address@hidden>
+
+       Avoid regressions in trace and comment output.
+       * doc/m4.texinfo (Trace): Add test.
+       (Comments): Likewise.
+
+2008-07-28  Eric Blake  <address@hidden>
+
+       Optimize iteration examples.
+       * examples/forloop2.m4: Avoid excess indir, by passing current
+       counter value as parameter.
+       * examples/foreachq3.m4: Avoid unneeded ifelse, by injecting an
+       ignored argument.
+       * doc/m4.texinfo (Improved forloop, Improved foreach): Update the
+       documentation to match.
+
+2008-07-26  Eric Blake  <address@hidden>
+
+       Give example for O(n) foreach on m4 1.4.x.
+       * examples/foreachq4.m4: New file.
+       * examples/Makefile.am (EXTRA_DIST): Distribute it.
+       * doc/m4.texinfo (Improved foreach): Document linear foreach with
+       m4 1.4.5 and greater.
+
+2008-07-17  Eric Blake  <address@hidden>
+
+       Fix missing copyright notices.
+       * acinclude.m4: Add copyright license details.
+       * c-boxes.el: Likewise.
+       * checks/get-them: Likewise.
+       * checks/check-them: Likewise.
+
+2008-07-13  Eric Blake  <address@hidden>
+
+       Add -g/--gnu command line argument.
+       * src/m4.c (usage): Mention the new option.
+       (long_options, OPTSTRING): Add new option.
+       (main): Use it.
+       * NEWS: Document this addition.
+       * doc/m4.texinfo (Limits control): Likewise.
+       (Incompatibilities): Mention future use of POSIXLY_CORRECT.
+       * THANKS: Update.
+       Reported by Joel E. Denny.
+
+2008-07-11  Eric Blake  <address@hidden>
+
+       Avoid bogus whitespace in @ovar, @dvar.
+       * doc/m4.texinfo (ovar, dvar): Add @c.
+       Based on patch by Ralf Wildenhues to Autoconf manual.
+
+2008-06-16  Eric Blake  <address@hidden>
+
+       Add missing const qualifications.
+       * src/builtin.c (builtin_tab): Declare array elements as const.
+
+2008-06-03  Eric Blake  <address@hidden>
+
+       Use progname module rather than rolling our own program_name.
+       * m4/gnulib-cache.m4: Import progname module.
+       * src/m4.c (program_name): Replace...
+       (main): ...with a call to set_program_name.
+
+2008-06-02  Eric Blake  <address@hidden>
+
+       Allow autobuild usage.
+       * m4/gnulib.cache: Import autobuild module.
+
+2008-05-23  Eric Blake  <address@hidden>
+
+       Make closing files be consistent.
+       * src/freeze.c (reload_frozen_state): Use close_stream.
+       Reported by Jean-Charles Longuet.
+
+2008-05-22  Eric Blake  <address@hidden>
+
+       Don't allow failure to freeze give exit status of 0.
+       * src/freeze.c (produce_frozen_state): Guarantee non-zero exit on
+       fopen failure.
+       * doc/m4.texinfo (Using frozen files): Test the fix.
+       * THANKS: Update.
+       Reported by Jean-Charles Longuet.
+
+2008-05-09  Eric Blake  <address@hidden>
+
+       Improve error message when frozen file is invalid.
+       * src/freeze.c (reload_frozen_state): Track current line.
+       [GET_STRING]: New helper macro.
+
+2008-05-09  Eric Blake  <address@hidden>
+
+       Detect integer overflow when loading frozen file.
+       * src/m4.h (includes): Add limits.h.
+       (_): Define as a no-op placeholder for now.
+       * src/freeze.c (reload_frozen_state) [GET_NUMBER]: Rewrite to fail
+       immediately on overflow.
+       Reported by Jim Meyering.
+
+2008-05-07  Eric Blake  <address@hidden>
+
+       Fix traceon regression introduced 2006-06-06.
+       * src/builtin.m4 (traceon): Only perform insertion if lookup
+       fails.
+       * doc/m4.texinfo (Trace): Test for the bug.
+       * NEWS: Document it.
+
+2008-05-03  Eric Blake  <address@hidden>
+
+       Document define_blind.
+       * doc/m4.texinfo (Ifelse): Add a new composite macro.
+       * THANKS: Update.
+       Suggested by Mike R.
+
+2008-04-24  Eric Blake  <address@hidden>
+
+       Add debugmode test.
+       * doc/m4.texinfo (Debug Levels): Test -di behavior.
+       (Changeword, Location): Correct examples.
+       * checks/check-them (examples): Update to account for recommended
+       location for running tests.
+       * doc/m4.texinfo (Debug Levels): Test this behavior.
+
+2008-04-21  Eric Blake  <address@hidden>
+
+       Fix spelling of attribution to Christopher Strachey.
+       * doc/m4.texinfo (History, Inhibiting Invocation): Fix typo.
+       * THANKS: Update.
+       Reported by Fernando Carrijo.
+
+2008-04-17  Eric Blake  <address@hidden>
+
+       Fix buildbot failure.
+       * doc/m4.texinfo (Diversions): Consume all of m4's output, in case
+       SIGPIPE is ignored.
+       * THANKS: Update.
+       Detected by Bob Proulx's buildbot.
+
+2008-04-17  Eric Blake  <address@hidden>
+
+       Avoid gcc shadowing warnings.
+       * src/builtin.c (m4_format): s/format/expand_format, so local
+       variables can be named format.
+       * src/format.c (format): Rename...
+       (expand_format): ...to this, and avoid the name index.
+       * src/input.c (push_file): Avoid the name close.
+       * src/m4.h (expand_format): Adjust prototype.
+       * src/output.c (threshold_diversion_CB): Avoid the name div.
+
+2008-04-15  Eric Blake  <address@hidden>
+
+       Another 'make installcheck' fix.
+       * doc/m4.texinfo (Diversions): s/m4/__program__/ in case
+       --program-prefix was active.
+
+2008-04-11  Eric Blake  <address@hidden>
+
+       Ensure --program-prefix doesn't regress.
+       * Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Enforce change from
+       2008-03-10 by testing it at 'make distcheck' time.
+
+2008-04-11  Eric Blake  <address@hidden>
+
+       Improve OS/2+emx build.
+       * src/m4.h [__EMX__]: OS/2 does not have a Unix-compatible
+       system(3), no matter what other macros it pre-defined.
+       * doc/m4.texinfo (Mkstemp): Rework test to avoid globbing failure
+       on OS/2.
+       * src/builtin.c (predefined_tab): Ensure all possible system
+       identifiers are defined, not just the first; the testsuite will
+       catch if multiple identifiers mistakenly made it through.
+       * THANKS: Update.
+       Reported by Elbert Pol.
+
+2008-04-09  Eric Blake  <address@hidden>
+
+       Remove redundant configure macros.
+       * configure.ac (AC_CANONICAL_BUILD, AC_CANONICAL_HOST)
+       (AC_SYS_LARGEFILE, AC_TYPE_SIZE_T): Delete, since gnulib does
+       this.
+       (AC_CHECK_HEADERS_ONCE): Remove limits.h.
+
+2008-08-07  Bruno Haible  <address@hidden>  (tiny change)
+
+       Run m4 tests prior to gnulib unit tests.
+       * Makefile.am (SUBDIRS): Swap order of directories.
+
 2008-04-02  Eric Blake  <address@hidden>
 
        Release Version 1.4.11.
diff --git a/HACKING b/HACKING
index 2f7ecdb..ad59990 100644
--- a/HACKING
+++ b/HACKING
@@ -62,6 +62,13 @@ and is not part of a release distribution.
   Note that none of these bootstrapping dependencies should be required
   by a distributed release.
 
+* M4 has an optional build dependency.  In order to ensure that the
+  dependency remains optional, you can avoid the library by using
+  `./configure --without-libsigsegv-prefix'.  In order to ensure that
+  the dependency is still viable with the current code base, you should
+  install:
+  - Libsigsegv 2.5 or later
+
 * Either add the gnulib directory to your PATH, or run
     GNULIB_TOOL=path/to/gnulib/gnulib-tool ./bootstrap
 
@@ -250,6 +257,11 @@ yyyy-mm-dd  Name of Author  <address@hidden>  (tiny change)
 * For non-alpha releases, update the webpages.  Replace manual.html with
   the new one (generate with `make web-manual').
 
+* Update the Free Software Directory.  Checkout the CVS sources:
+    cvs -d :pserver:address@hidden:/sources/directory \
+      co directory/m4.txt
+  After making edits, mail the diff to <address@hidden>.
+
 -- 
 Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
diff --git a/Makefile.am b/Makefile.am
index a67b415..4f4a60b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,7 +20,7 @@
 ##
 ## Written by Gary V. Vaughan <address@hidden>
 
-SUBDIRS = . examples lib src doc tests checks
+SUBDIRS = . examples lib src doc checks tests
 EXTRA_DIST = bootstrap c-boxes.el cfg.mk maint.mk \
        .version m4/gnulib-cache.m4
 DISTCLEANFILES = stamp-h
@@ -32,7 +32,9 @@ MAINTAINERCLEANFILES = COPYING INSTALL Makefile.in aclocal.m4 
\
        m4/gnulib-tool.m4 missing stamp-h.in
 
 ACLOCAL_AMFLAGS = -I m4
-DISTCHECK_CONFIGURE_FLAGS = --enable-changeword
+## Enough users install GNU M4 as gm4 that we make sure 'make installcheck'
+## will handle that, prior to making a release.
+DISTCHECK_CONFIGURE_FLAGS = --enable-changeword --program-prefix=g
 
 BUILT_SOURCES = $(top_srcdir)/.version
 $(top_srcdir)/.version:
diff --git a/NEWS b/NEWS
index b609525..a208c3f 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,35 @@ GNU M4 NEWS - User visible changes.
 Copyright (C) 1992, 1993, 1994, 2004, 2005, 2006, 2007, 2008 Free Software
 Foundation, Inc.
 
+* Noteworthy changes in Version 1.4.12 (2008-??-??) [stable]
+  Released by Eric Blake, based on git version 1.4.11.*
+
+** Fix regression introduced in 1.4.4b where using `traceon' could delete
+   a macro.  This was most noticeable with `traceon(`traceon')', but
+   would also happen in cases such as `foo(traceon(`foo'))'.
+
+** New `-g'/`--gnu' command-line option overrides `-G'/`--traditional'.
+   For now, the environment variable POSIXLY_CORRECT has no effect on M4
+   behavior; but a future release of M4 will behave as though --traditional
+   is implied if POSIXLY_CORRECT is set (this future change is necessary,
+   because in the current release, there is no way to disable GNU
+   extensions that conflict with POSIX without the use of a non-POSIX
+   command-line argument).  Clients of M4 that want to use GNU extensions,
+   even when POSIXLY_CORRECT is set, should start using the -g command-line
+   argument, even though it is currently a no-op if -G did not appear
+   earlier in the command line, so that the client will not break in the
+   face of an upgraded m4 and a POSIXLY_CORRECT execution environment.
+
+** The `-L'/`--nesting-limit' command-line option now defaults to 0 for
+   unlimited on platforms that can detect and deal with stack overflow.  On
+   systems that lack alternate stack support, such as Cygwin, and on
+   systems that do not obey the POSIX semantics for distinguishing stack
+   overflow from other exceptions, such as Linux, you can optionally
+   install the libsigsegv library to enhance m4's ability to accurately
+   report stack overflow: http://www.gnu.org/software/libsigsegv/
+
+** A number of portability improvements inherited from gnulib.
+
 * Noteworthy changes in Version 1.4.11 (2008-04-02) [stable]
   Released by Eric Blake, based on git version 1.4.10a
 
diff --git a/README b/README
index 9fb5675..fa9ead4 100644
--- a/README
+++ b/README
@@ -19,6 +19,15 @@ ahead and start with `./configure'.  If you are trying to 
build `m4'
 from git, more information can be found in the version-control-only
 file HACKING.
 
+M4 has an optional dependency on the libsigsegv library:
+  http://www.gnu.org/software/libsigsegv/
+If the library has not been installed in the standard location, you
+can use `./configure --with-libsigsegv-prefix=/path/to/dir', to make
+the build of `m4' use /path/to/dir/include/sigsegv.h as appropriate.
+The use of this library is optional; the only difference in having it
+available is that it increases the number of platforms where `m4' can
+correctly distinguish stack overflow from an internal bug.
+
 In the subdirectory `examples' you will find various m4 files, ranging
 from trivial test files to rather advanced macros.  If you intend to
 use m4 seriously, you might find useful material down there.
diff --git a/THANKS b/THANKS
index 01c560f..6a048b9 100644
--- a/THANKS
+++ b/THANKS
@@ -21,6 +21,7 @@ Bengt Mertensson      address@hidden
 Bernhard Daeubler      address@hidden
 Bjorn R. Bjornsson     address@hidden
 Bob Badour             address@hidden
+Bob Proulx             address@hidden
 Brendan Kehoe          address@hidden
 Bruno Haible           address@hidden
 Cesar Strauss          address@hidden
@@ -29,10 +30,12 @@ Damian Menscher             address@hidden
 Dan Jacobson           address@hidden
 David J. MacKenzie     address@hidden
 David Perlin           address@hidden
+Elbert Pol             address@hidden
 Erez Zadok             address@hidden
 Eric Allman            address@hidden
 Eric Backus            address@hidden
 Eric Blake             address@hidden
+Fernando Carrijo       address@hidden
 François Pinard               address@hidden
 Frank Schwidom         address@hidden
 Gary V. Vaughan                address@hidden
@@ -44,9 +47,11 @@ Hoang Uong           address@hidden
 Ian Taylor             address@hidden
 Ilya N. Golubev                address@hidden
 Jason Merrill          address@hidden
+Jean-Charles Longuet   address@hidden
 Jim Avera              address@hidden
 Jim Kingdom            address@hidden
 Jim Meyering           address@hidden
+Joel E. Denny          address@hidden
 Joel Sherrill          address@hidden
 John Brzustowski       address@hidden
 John David Anglin      address@hidden
@@ -71,6 +76,7 @@ Michael Fetterman     address@hidden
 Michael L. Welcome     address@hidden
 Mike Frysinger         address@hidden
 Mike Lijewski          address@hidden
+Mike R.                        address@hidden
 Mikhail Teterin                address@hidden
 Nelson H. F. Beebe     address@hidden
 Nick S. Kanakakorn     address@hidden
diff --git a/acinclude.m4 b/acinclude.m4
index ae569bc..c14a5e3 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -1,6 +1,10 @@
 # Local additions to Autoconf macros.
-# Copyright (C) 1992, 1994, 2004, 2006 Free Software Foundation, Inc.
+# Copyright (C) 1992, 1994, 2004, 2006, 2008 Free Software Foundation, Inc.
 # Francois Pinard <address@hidden>, 1992.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
 
 # Check if --with-dmalloc was given.
 
diff --git a/c-boxes.el b/c-boxes.el
index c1b80e3..35e4d99 100644
--- a/c-boxes.el
+++ b/c-boxes.el
@@ -1,7 +1,22 @@
 ;;; Boxed comments for C mode.
-;;; Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+;;; Copyright (C) 1991, 1992, 1993, 1994, 2008 Free Software Foundation, Inc.
 ;;; Francois Pinard <address@hidden>, April 1991.
 ;;;
+;;; This file is part of GNU M4.
+;;;
+;;; GNU M4 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.
+;;;
+;;; GNU M4 is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
 ;;; I often refill paragraphs inside C comments, while stretching or
 ;;; shrinking the surrounding box as needed.  This is a real pain to
 ;;; do by hand.  Here is the code I made to ease my life on this,
diff --git a/checks/Makefile.in b/checks/Makefile.in
index 0e1091e..c43c2cc 100644
--- a/checks/Makefile.in
+++ b/checks/Makefile.in
@@ -36,14 +36,16 @@ program_transform_name = @program_transform_name@
 AWK = @AWK@
 
 # Vern says that the first star is required around an Alpha make bug.
-CHECKS = $(srcdir)/*[0-9][0-9][0-9].*
+DOC_CHECKS = $(srcdir)/*[0-9][0-9][0-9].*
+CHECKS = $(DOC_CHECKS) $(srcdir)/stackovf.test
 # Makefile.in is automatically distributed by automake.
-DISTFILES = $(srcdir)/get-them $(srcdir)/check-them $(srcdir)/stamp-checks
+DISTFILES = $(srcdir)/get-them $(srcdir)/check-them $(srcdir)/stamp-checks \
+       $(srcdir)/stackovf.test
 
 all: $(srcdir)/stamp-checks
 
 $(srcdir)/stamp-checks: $(srcdir)/get-them $(srcdir)/../doc/m4.texinfo
-       rm -f $(CHECKS)
+       rm -f $(DOC_CHECKS)
        cd $(srcdir) && AWK=$(AWK) ./get-them ../doc/m4.texinfo
        touch $(srcdir)/stamp-checks
 
@@ -73,13 +75,13 @@ distclean: clean
        rm -f Makefile
 
 maintainer-clean realclean: distclean
-       rm -f $(CHECKS) $(srcdir)/stamp-checks
+       rm -f $(DOC_CHECKS) $(srcdir)/stamp-checks
 
 distdir: dist
 
 dist: $(DISTFILES)
        @echo "Copying distribution files"
-       @for file in $(DISTFILES) $(CHECKS); do \
+       @for file in $(DISTFILES) $(DOC_CHECKS); do \
          ln $$file ../$(PACKAGE)-$(VERSION)/checks 2> /dev/null \
            || cp -p $$file ../$(PACKAGE)-$(VERSION)/checks; \
        done
diff --git a/checks/check-them b/checks/check-them
index 0a697f5..fac1b2b 100755
--- a/checks/check-them
+++ b/checks/check-them
@@ -1,6 +1,21 @@
 #!/bin/sh
 # Check GNU m4 against examples from the manual source.
 # Copyright (C) 1992, 2006, 2007, 2008 Free Software Foundation, Inc.
+#
+# This file is part of GNU M4.
+#
+# GNU M4 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.
+#
+# GNU M4 is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 # Clean up temp files on exit
 pwd=`pwd`
@@ -70,6 +85,18 @@ do
     continue
   }
   echo "Checking $file"
+
+  case $file in
+    *stackovf.test)
+      "$file" "$m4"
+      case $? in
+       77) skipped="$skipped $file";;
+       0) ;;
+       *) failed="$failed $file"
+      esac
+      continue ;;
+  esac
+
   options=`sed -ne '3s/^dnl @ extra options: //p;3q' "$file"`
   sed -e '/^dnl @/d' -e '/^\^D$/q' "$file" \
     | LC_MESSAGES=C M4PATH=$examples "$m4" -d $options - >$out 2>$err
@@ -92,7 +119,7 @@ do
 
   xoutfile=`sed -n 's/^dnl @ expected output: //p' "$file"`
   if test -z "$xoutfile" ; then
-    sed -e '/^dnl @result{}/!d' -e 's///' -e "s|\.\./examples|$examples|" \
+    sed -e '/^dnl @result{}/!d' -e 's///' -e "s|examples/|$examples/|" \
       "$file" > $xout
   else
     cp "$examples/$xoutfile" $xout
@@ -101,10 +128,10 @@ do
   xerrfile=`sed -n 's/^dnl @ expected error: //p' "$file"`
   if test -z "$xerrfile" ; then
     sed '/^dnl @error{}/!d
-         s///; '"s|^m4:|$m4name:|; s|\.\./examples|$examples|" \
+        s///; '"s|^m4:|$m4name:|; s|examples/|$examples/|" \
       "$file" > $xerr
   else
-    sed "s|^m4:|$m4name:|; s|\.\./examples|$examples|" \
+    sed "s|^m4:|$m4name:|; s|examples/|$examples/|" \
       "$examples/$xerrfile" > $xerr
   fi
 
diff --git a/checks/get-them b/checks/get-them
index 803f413..6e571f0 100755
--- a/checks/get-them
+++ b/checks/get-them
@@ -3,6 +3,21 @@
 # Extract all examples from the manual source.
 # Copyright (C) 1992, 2005, 2006, 2007, 2008 Free Software Foundation,
 # Inc.
+#
+# This file is part of GNU M4.
+#
+# GNU M4 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.
+#
+# GNU M4 is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 # This script is for use with GNU awk.
 
@@ -79,7 +94,8 @@ BEGIN {
     printf("dnl @ %s:%d: Origin of test\n"\
           "dnl @ expected status: %d\n"\
           "dnl @ extra options: %s\n"\
-          "dnl @ Copyright (C) 2006, 2007 Free Software Foundation\n"\
+          "dnl @ Copyright (C) 2006, 2007, 2008 Free Software Foundation,\n"\
+          "dnl @ Inc.\n"\
           "dnl @ This file is free software; the Free Software Foundation\n"\
           "dnl @ gives unlimited permission to copy and/or distribute it\n"\
           "dnl @ with or without modifications, as long as this notice\n"\
diff --git a/checks/stackovf.test b/checks/stackovf.test
new file mode 100755
index 0000000..0ab0ccb
--- /dev/null
+++ b/checks/stackovf.test
@@ -0,0 +1,99 @@
+#!/bin/sh
+# This file is part of the GNU m4 testsuite
+# Copyright (C) 2000, 2003, 2007, 2008 Free Software Foundation, Inc.
+#
+# This file is part of GNU M4.
+#
+# GNU M4 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.
+#
+# GNU M4 is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Script to verify that stack overflow is diagnosed properly when
+# there is infinite macro call nesting, provided the OS supports it.
+
+m4="$1"
+
+# Skip this test if -L defaults to 1024 instead of 0, as that is our
+# indicator that the OS does not support stack overflow detection.
+("$m4" --help | grep 'nesting.*\[0\]') >/dev/null 2>&1 \
+  || {
+       echo "$0: skipping test, no stack overflow support detected in $m4"
+       exit 77
+     }
+
+# On some systems the ulimit command is available in ksh or bash but not sh
+(exec 2>/dev/null; ulimit -Ss 300) || {
+  for altshell in bash bsh ksh zsh ; do
+    if (exec >/dev/null 2>&1; $altshell -c 'ulimit -Ss 300') && test -z "$2"
+    then
+      echo "Using $altshell because it supports ulimit"
+      exec $altshell "$0" "$@" running-with-$altshell
+      exit 1
+    fi
+  done
+}
+
+tmpdir=
+trap 'st=$?; rm -rf "$tmpdir" && exit $st' 0
+trap '(exit $?); exit $?' 1 2 3 15
+
+# Create a temporary subdirectory $tmpdir in $TMPDIR (default /tmp).
+# Use mktemp if possible; otherwise fall back on mkdir,
+# with $RANDOM to make collisions less likely.
+: ${TMPDIR=/tmp}
+{
+  tmpdir=`
+    (umask 077 && mktemp -d "$TMPDIR/m4stk-XXXXXX") 2>/dev/null
+  ` &&
+  test -n "$tmpdir" && test -d "$tmpdir"
+} || {
+  tmpdir=$TMPDIR/m4stk-$$-$RANDOM
+  (umask 077 && mkdir "$tmpdir")
+} || exit $?
+tmpfile="$tmpdir"/m4.out
+
+# Limit the stack size if the shell we are running permits it
+if (exec 2>/dev/null; ulimit -Ss 300)
+then
+  ulimit -Ss 300
+  echo "Stack soft limit set to `ulimit -s`K";
+else
+  echo "Can't reset stack limit - this may take a while..."
+fi
+
+# Induce stack overflow.
+echo 'define(a,a(a))a' | "$m4" > "$tmpfile" 2>&1
+result=$?
+
+exitcode=1
+if test $result -eq 0 ; then
+  echo "Failure - $m4 did not abort"
+else
+  # See if stack overflow was diagnosed.
+  case `cat "$tmpfile"` in
+    *stack\ overflow*)
+      case `echo "$tmpdir"/*` in
+       $tmpfile)
+          echo "Pass"
+          exitcode=0 ;;
+       *) echo "Failure - $m4 created unexpected core dump"
+          ls -l "$tmpdir" ;;
+      esac ;;
+    *) echo "Failure - $m4 aborted unexpectedly";
+       ;;
+    esac
+fi
+
+test $exitcode = 0 ||
+    { echo "Output from $m4:"; cat $tmpfile; }
+
+exit $exitcode
diff --git a/configure.ac b/configure.ac
index 990c8f6..f23cc42 100644
--- a/configure.ac
+++ b/configure.ac
@@ -29,33 +29,11 @@ m4_pattern_forbid([^M4_[A-Z]])
 AC_CONFIG_SRCDIR([src/m4.h])
 AC_CONFIG_HEADERS([lib/config.h:lib/config.hin])
 
-AC_CANONICAL_BUILD
-AC_CANONICAL_HOST
 AC_PROG_CC
 M4_EARLY
 
-AC_SYS_LARGEFILE
-AC_CHECK_HEADERS_ONCE([limits.h siginfo.h sys/wait.h])
-AC_CHECK_TYPES([siginfo_t], [], [],
-[[#include <signal.h>
-#if HAVE_SIGINFO_H
-# include <siginfo.h>
-#endif
-]])
-AC_CHECK_MEMBERS([struct sigaction.sa_sigaction], [], [],
-[[#include <signal.h>
-]])
-AC_CHECK_MEMBERS([stack_t.ss_sp], [], [],
-[[#include <signal.h>
-#if HAVE_SIGINFO_H
-# include <siginfo.h>
-#endif
-]])
-
-AC_TYPE_SIGNAL
-AC_TYPE_SIZE_T
-
-AC_CHECK_FUNCS_ONCE([sigaction sigaltstack sigstack sigvec strerror])
+# M4 is single-threaded; so we can optimize gnulib code by using this:
+gl_DISABLE_THREADS
 
 # Tandem/NSK is broken - it has 'long long int' but not
 # 'unsigned long long int', which confuses assumptions made by gnulib.
@@ -71,45 +49,6 @@ fi
 
 M4_INIT
 
-# Code from Jim Avera <address@hidden>.
-# stackovf.c requires:
-#  1. Either sigaction with SA_ONSTACK, or sigvec with SV_ONSTACK
-#  2. Either sigaltstack or sigstack
-#  3. getrlimit, including support for RLIMIT_STACK
-AC_CACHE_CHECK([if stack overflow is detectable], [M4_cv_use_stackovf],
-[M4_cv_use_stackovf=no
-if test "$ac_cv_func_sigaction" = yes || test "$ac_cv_func_sigvec" = yes; then
-  if test "$ac_cv_func_sigaltstack" = yes || test "$ac_cv_func_sigstack" = 
yes; then
-    AC_LINK_IFELSE([AC_LANG_PROGRAM([[
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <signal.h>
-]], [[struct rlimit r; getrlimit (RLIMIT_STACK, &r);
-#if (!defined(HAVE_SIGACTION) || !defined(SA_ONSTACK)) \
-    && (!defined(HAVE_SIGVEC) || !defined(SV_ONSTACK))
-choke me               /* SA_ONSTACK and/or SV_ONSTACK are not defined */
-#endif
-]])], [M4_cv_use_stackovf=yes])
-  fi
-fi])
-AM_CONDITIONAL([STACKOVF], [test "$M4_cv_use_stackovf" = yes])
-if test "$M4_cv_use_stackovf" = yes; then
-  AC_DEFINE([USE_STACKOVF], [1],
-    [Define to 1 if using stack overflow detection])
-  AC_CHECK_TYPES([rlim_t], [],
-    [AC_DEFINE([rlim_t], [int],
-      [Define to int if rlim_t is not defined in sys/resource.h])],
-    [[#include <sys/resource.h>
-  ]])
-  AC_CHECK_TYPES([stack_t], [],
-    [AC_DEFINE([stack_t], [struct sigaltstack],
-      [Define to struct sigaltstack if stack_t is not in signal.h])],
-    [[#include <signal.h>
-  ]])
-  AC_CHECK_TYPES([sigcontext], [], [], [[#include <signal.h>
-  ]])
-fi
-
 AC_CACHE_CHECK([if system() agrees with pclose()],
   [M4_cv_func_system_consistent],
   [AC_RUN_IFELSE([AC_LANG_PROGRAM([
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index 02e0f6d..300fb79 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -21,17 +21,17 @@
 @c @ovar{ARG}
 @c -------------------
 @c The ARG is an optional argument.  To be used for macro arguments in
address@hidden their documentation.
address@hidden their documentation (@defmac).
 @macro ovar{varname}
address@hidden@address@hidden
address@hidden@address@hidden@c
 @end macro
 
 @c @dvar{ARG, DEFAULT}
 @c -------------------
 @c The ARG is an optional argument, defaulting to DEFAULT.  To be used
address@hidden for macro arguments in their documentation.
address@hidden for macro arguments in their documentation (@defmac).
 @macro dvar{varname, default}
address@hidden@var{\varname\} = @address@hidden
address@hidden@var{\varname\} = @address@hidden@c
 @end macro
 
 @comment %**end of header
@@ -346,7 +346,7 @@ debugging their @code{m4} scripts than doing real work.  
Beware that
 @cindex history of @code{m4}
 @cindex @acronym{GNU} M4, history of
 @code{GPM} was an important ancestor of @code{m4}.  See
-C. Stratchey: ``A General Purpose Macro generator'', Computer Journal
+C. Strachey: ``A General Purpose Macro generator'', Computer Journal
 8,3 (1965), pp.@: 225 ff.  @code{GPM} is also succinctly described into
 David Gries classic ``Compiler Construction for Digital Computers''.
 
@@ -739,6 +739,23 @@ only by your hardware and operating system constraints) in 
@acronym{GNU}
 @code{m4}.
 
 @table @code
address@hidden -g
address@hidden --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 @option{--traditional}.  However, having
address@hidden behavior as default makes it impossible to write a
+strictly @acronym{POSIX}-compliant client that avoids all incompatible
address@hidden M4 extensions, since such a client would have to use the
address@hidden command-line option to force full @acronym{POSIX}
+behavior.  Thus, a future version of M4 will be changed to implicitly
+use the option @option{--traditional} if the environment variable
address@hidden is set.  Projects that intentionally use
address@hidden extensions should consider using @option{--gnu} to state
+their intentions, so that the project will not mysteriously break if the
+user upgrades to a newer M4 and has @env{POSIXLY_CORRECT} set in their
+environment.
+
 @item -G
 @itemx --traditional
 Suppress all the extensions made in this implementation, compared to the
@@ -757,15 +774,16 @@ increase this value, unless you define an excessive 
number of macros.
 @cindex limit, nesting
 Artificially limit the nesting of macro calls to @var{NUM} levels,
 stopping program execution if this limit is ever exceeded.  When not
-specified, nesting is limited to 1024 levels.  A value of zero means
+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 might be more correctly associated
+The precise effect of this option is more correctly associated
 with textual nesting than dynamic recursion.  It has been useful
-when some complex @code{m4} input was generated by mechanical means.
-Most users would never need this option.  If shown to be obtrusive,
-this option (which is still experimental) might well disappear.
+when some complex @code{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.
 
 @cindex rescanning
 This option does @emph{not} have the ability to break endless
@@ -998,6 +1016,27 @@ The comment delimiters can be changed to any string at 
any time, using
 the builtin macro @code{changecom}.  @xref{Changecom}, for more
 information.
 
address@hidden
address@hidden Detect regression in 1.4.10b in regards to reparsing comments.
address@hidden Not worth including in the manual.
address@hidden
+define(`e', `$@@')define(`q', ``$@@'')define(`foo', `bar')
address@hidden
+q(e(`one
+',#two ' foo
+))
address@hidden
address@hidden',`#two  bar
address@hidden''
+changecom(`<', `>')define(`n', `$#')
address@hidden
+n(e(<`>, <'>))
address@hidden
+len(e(<`>, ,<'>))
address@hidden
address@hidden example
address@hidden ignore
+
 @node Other tokens
 @section Other kinds of input tokens
 
@@ -1250,7 +1289,7 @@ with no arguments.
 @section Preventing macro invocation
 
 An innovation of the @code{m4} language, compared to some of its
-predecessors (like Stratchey's @code{GPM}, for example), is the ability
+predecessors (like Strachey's @code{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, @acronym{GNU}
@@ -2643,6 +2682,63 @@ 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
+
 @cindex multibranches
 @cindex switch statement
 @cindex case statement
@@ -3477,6 +3573,16 @@ does not transfer tracing status.
 
 @example
 $ @kbd{m4 -d}
+traceon(`traceon')
address@hidden
+traceon(`traceoff')
address@hidden: -1- traceon(`traceoff')
address@hidden
+traceoff(`traceoff')
address@hidden: -1- traceoff(`traceoff')
address@hidden
+traceoff(`traceon')
address@hidden
 traceon(`eval', `m4_divnum')
 @result{}
 define(`m4_eval', defn(`eval'))
@@ -3494,6 +3600,22 @@ m4_eval(m4_divnum)
 @xref{Debug Levels}, for information on controlling the details of the
 display.
 
address@hidden
address@hidden not worth including in the manual, but this tests a trace code
address@hidden path that was temporarily broken
address@hidden options: -de --trace ifelse
address@hidden
+$ @kbd{m4 -de --trace ifelse}
+define(`e', `ifelse(`$1', `$2', `ifelse(`$1', `$2', `e(shift($@@))')')')
address@hidden
+e(`1', `1')
address@hidden: -1- ifelse -> ifelse(`1', `1', `e(shift(`1',`1'))')
address@hidden: -1- ifelse -> e(shift(`1',`1'))
address@hidden: -1- ifelse
address@hidden
address@hidden example
address@hidden ignore
+
 @node Debug Levels
 @section Controlling debugging output
 
@@ -3608,6 +3730,42 @@ foo
 @result{}FOO
 @end example
 
+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.
+
address@hidden options: -l6
address@hidden
+$ @kbd{m4 -d -l 6}
+define(`echo', `$@@')debugmode(`+t')
address@hidden
+echo(`1', `long string')
address@hidden: -1- echo(`1', `long s...') -> ``1',`l...'
address@hidden,long string
+indir(`echo', defn(`changequote'))
address@hidden: -2- defn(`change...')
address@hidden: -1- indir(`echo', <changequote>) -> ``''
address@hidden
address@hidden example
+
+This example shows the effects of the debug flags that are not related
+to macro tracing.
+
address@hidden examples
address@hidden options: -dip
address@hidden
+$ @kbd{m4 -dip -I examples}
address@hidden: input read from stdin
+include(`foo')dnl
address@hidden: path search for `foo' found `examples/foo'
address@hidden: input read from examples/foo
address@hidden
address@hidden: input reverted to stdin, line 1
+^D
address@hidden: input exhausted
address@hidden example
+
 @node Debug Output
 @section Saving debugging output
 
@@ -4259,7 +4417,7 @@ define(`bar
 ', defn(`__file__'))
 @result{}
 include(`foo')
address@hidden/examples/foo
address@hidden/foo
 define(`bar
 ', defn(`__line__'))
 @result{}
@@ -4714,7 +4872,7 @@ ifdef(`__unix__', ,
 ')m4exit(`77')')dnl
 changequote(`[', `]')dnl
 syscmd([echo 'divert(1)hi
-format(%1000000d, 1)' | m4 | sed 1q])dnl
+format(%1000000d, 1)' | ]__program__[ | sed -n 1p])dnl
 @result{}hi
 sysval
 @result{}0
@@ -6237,11 +6395,13 @@ sysval
 @c the expansion.
 
 @example
-syscmd(`rm -f foo??????')sysval
+syscmd(`rm -rf foodir')sysval
 @result{}0
-len(mkstemp(`fooXXXXX'))
address@hidden
-syscmd(`rm foo??????')sysval
+syscmd(`mkdir foodir')sysval
address@hidden
+len(mkstemp(`foodir/fooXXXXX'))
address@hidden
+syscmd(`rm -r foodir')sysval
 @result{}0
 @end example
 
@@ -6360,7 +6520,7 @@ foo
 @result{}foo called at stdin:2
 include(`incl.m4')
 @result{}Include file start
address@hidden called at ../examples/incl.m4:2
address@hidden called at examples/incl.m4:2
 @result{}Include file end
 @result{}
 @end example
@@ -6590,6 +6750,16 @@ ifdef(`__unix__', ,
 ')m4exit(`77')')dnl
 traceon(`undefined')dnl
 @end example
+
address@hidden Make sure freezing is successful.
+
address@hidden options: -F /none/such
address@hidden status: 1
address@hidden
+$ @kbd{m4 -F /none/such}
+^D
address@hidden: cannot open /none/such: No such file or directory
address@hidden example
 @end ignore
 
 When an @code{m4} run is to be frozen, the automatic undiversion
@@ -6965,6 +7135,22 @@ However, this appears to be a bug in @acronym{POSIX}, 
since most
 traditional implementations also ignore all whitespace (formfeed,
 carriage return, and vertical tab).  @acronym{GNU} @code{m4} follows
 tradition and ignores all leading unquoted whitespace.
+
address@hidden
address@hidden @env{POSIXLY_CORRECT}
+A strictly-compliant @acronym{POSIX} client is not allowed to use
+command-line arguments not specified by @acronym{POSIX}.  However, since
+this version of M4 ignores @env{POSIXLY_CORRECT} and enables the option
address@hidden by default (@pxref{Limits control, , Invoking m4}), a
+client desiring to be strictly compliant has no way to disable
address@hidden extensions that conflict with @acronym{POSIX} when
+directly invoking the compiled @code{m4}.  A future version of
address@hidden M4 will honor the environment variable @env{POSIXLY_CORRECT},
+implicitly enabling @option{--traditional} if it is set, in order to
+allow a strictly-compliant client.  In the meantime, a client needing
+strict @acronym{POSIX} compliance can use the workaround of invoking a
+shell script wrapper, where the wrapper then adds @option{--traditional}
+to the arguments passed to the compiled @code{m4}.
 @end itemize
 
 @node Other Incompatibilities
@@ -7087,8 +7273,9 @@ 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 @address@hidden/@/examples/@/forloop2.m4}; this
-version also optimizes based on the fact that the starting bound does
-not need to be passed to the helper @address@hidden
+version also optimizes overhead by calling four macros instead of six
+per iteration (excluding those in @var{text}), by not dereferencing the
address@hidden in the helper @address@hidden
 
 @comment examples
 @example
@@ -7099,12 +7286,12 @@ undivert(`forloop2.m4')dnl
 @result{}#   works even if VAR is not a strict macro name
 @result{}#   performs sanity check that FROM is larger than TO
 @result{}#   allows complex numerical expressions in TO and FROM
address@hidden(`forloop', `ifelse(eval(`($3) >= ($2)'), `1',
address@hidden  `pushdef(`$1', eval(`$2'))_$0(`$1',
address@hidden(`forloop', `ifelse(eval(`($2) <= ($3)'), `1',
address@hidden  `pushdef(`$1')_$0(`$1', eval(`$2'),
 @result{}    eval(`$3'), `$4')popdef(`$1')')')
 @result{}define(`_forloop',
address@hidden  `$3`'ifelse(indir(`$1'), `$2', `',
address@hidden    `define(`$1', incr(indir(`$1')))$0($@@)')')
address@hidden  `define(`$1', `$2')$4`'ifelse(`$2', `$3', `',
address@hidden    `$0(`$1', incr(`$2'), `$3', `$4')')')
 @result{}divert`'dnl
 include(`forloop2.m4')
 @result{}
@@ -7115,7 +7302,7 @@ forloop(`', `1', `2', ` odd iterator name')
 forloop(`i', `5 + 5', `0xc', ` 0x`'eval(i, `16')')
 @result{} 0xa 0xb 0xc
 forloop(`i', `a', `b', `non-numeric bounds')
address@hidden:stdin:6: bad expression in eval (bad input): (b) >= (a)
address@hidden:stdin:6: bad expression in eval (bad input): (a) <= (b)
 @result{}
 @end example
 
@@ -7140,8 +7327,8 @@ define(`double', `define(`$1'`2',
   arg1(patsubst(dquote(defn(`$1')), `[`']', `\&\&')))')
 @result{}
 double(`forloop')double(`_forloop')defn(`forloop2')
address@hidden(eval(``($3) >= ($2)''), ``1'',
address@hidden  ``pushdef(``$1'', eval(``$2''))_$0(``$1'',
address@hidden(eval(``($2) <= ($3)''), ``1'',
address@hidden  ``pushdef(``$1'')_$0(``$1'', eval(``$2''),
 @result{}    eval(``$3''), ``$4'')popdef(``$1'')'')
 forloop(i, 1, 5, `ifelse(')forloop(i, 1, 5, `)')
 @result{}
@@ -7254,15 +7441,17 @@ helper method immediately, the 
@samp{defn(address@hidden')} no longer
 contains unexpanded macros.
 
 The astute m4 programmer might notice that the solution above still uses
-more memory, and thus more time, than strictly necessary.  Note that
address@hidden, which contains an arbitrarily long quoted list, is expanded
-and rescanned three times per iteration of @code{_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 @code{_foreachq} in order to operate on an
-unboxed list in the first place, and by using the fixed-length @samp{$#}
-instead of an arbitrary length list as the key to end recursion.  This
+more memory and macro invocations, and thus more time, than strictly
+necessary.  Note that @samp{$2}, which contains an arbitrarily long
+quoted list, is expanded and rescanned three times per iteration of
address@hidden 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 @code{_foreachq} in
+order to operate on an unboxed list in the first place, and by using the
+fixed-length @samp{$#} 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 @var{text}), instead of eight.  This
 alternative approach is available as
 @address@hidden/@/examples/@/foreach3.m4}:
 
@@ -7275,12 +7464,11 @@ undivert(`foreachq3.m4')dnl
 @result{}divert(`-1')
 @result{}# foreachq(x, `item_1, item_2, ..., item_n', stmt)
 @result{}#   quoted list, alternate improved version
address@hidden(`foreachq',
address@hidden(`$1')_$0(`$1', `$3'ifelse(`$2', `', `',
address@hidden  `, $2'))popdef(`$1')')
address@hidden(`_foreachq', `ifelse(`$#', `2', `',
address@hidden  `define(`$1', `$3')$2`'$0(`$1', `$2'ifelse(`$#', `3', `',
address@hidden    `, shift(shift(shift($@@)))'))')')
address@hidden(`foreachq', `ifelse(`$2', `', `',
address@hidden  `pushdef(`$1')_$0(`$1', `$3', `', $2)popdef(`$1')')')
address@hidden(`_foreachq', `ifelse(`$#', `3', `',
address@hidden  `define(`$1', `$4')$2`'$0(`$1', `$2',
address@hidden    shift(shift(shift($@@))))')')
 @result{}divert`'dnl
 traceon(`shift')debugmode(`aq')
 @result{}
@@ -7288,22 +7476,98 @@ foreachq(`x', ``1', `2', `3', `4'', `x
 ')dnl
 @result{}1
 @error{}m4trace: -4- shift(`x', `x
address@hidden', `', `1', `2', `3', `4')
address@hidden: -3- shift(`x
address@hidden', `', `1', `2', `3', `4')
address@hidden: -2- shift(`', `1', `2', `3', `4')
address@hidden
address@hidden: -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')
address@hidden
address@hidden
 @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')
address@hidden
address@hidden
 @error{}m4trace: -4- shift(`x', `x
 @error{}', `3', `4')
 @error{}m4trace: -3- shift(`x
 @error{}', `3', `4')
 @error{}m4trace: -2- shift(`3', `4')
address@hidden example
+
+In the current version of M4, every instance of @samp{$@@} is rescanned
+as it is encountered.  Thus, the @file{foreachq3.m4} alternative uses
+much less memory than @file{foreachq2.m4}, and executes as much as 10%
+faster, since each iteration encounters fewer @samp{$@@}.  However, the
+implementation of rescanning every byte in @samp{$@@} is quadratic in
+the number of bytes scanned (for example, making the broken version in
address@hidden 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 @code{foreachq} can
+become linear in the number of bytes scanned.  Notice how the
+implementation injects an empty argument prior to expanding @samp{$2}
+within @code{foreachq}; the helper macro @code{_foreachq} then ignores
+the third argument altogether, and ends recursion when there are three
+arguments left because there was nothing left to pass through
address@hidden  Thus, each iteration only needs one @code{ifelse}, rather
+than the two conditionals used in the version from @file{foreachq2.m4}.
+
address@hidden nine arguments, more than
address@hidden more than nine arguments
address@hidden arguments, more than nine
+So far, all of the implementations of @code{foreachq} presented have
+been quadratic with M4 1.4.x.  But @code{forloop} is linear, because
+each iteration parses a constant amount of arguments.  So, it is
+possible to design a variant that uses @code{forloop} to do the
+iteration, then uses @samp{$@@} only once at the end, giving a linear
+result even with older M4 implementations.  This implementation relies
+on the @acronym{GNU} extension that @samp{$10} expands to the tenth
+argument rather than the first argument concatenated with @samp{0}.  The
+trick is to define an intermediate macro that repeats the text
address@hidden(`$1', address@hidden')$2`'}, with @samp{n} set to successive
+integers corresponding to each argument.  The helper macro
address@hidden is needed in order to generate the literal sequences
+such as @samp{$1} into the intermediate macro, rather than expanding
+them as the arguments of @code{_foreachq}.  With this approach, no
address@hidden calls are even needed!  Even though there are seven macros
+of overhead per iteration instead of six in @file{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
address@hidden by no longer treating @samp{$10} as the tenth argument;
+the anticipation is that @address@hidden@}} can be used instead, although
+that alternative syntax is not yet supported.
+
address@hidden examples
address@hidden
+$ @kbd{m4 -I examples}
+include(`foreachq4.m4')
address@hidden
+undivert(`foreachq4.m4')dnl
address@hidden(`forloop2.m4')dnl
address@hidden(`-1')
address@hidden foreachq(x, `item_1, item_2, ..., item_n', stmt)
address@hidden   quoted list, version based on forloop
address@hidden(`foreachq',
address@hidden(`$2', `', `', `_$0(`$1', `$3', $2)')')
address@hidden(`_foreachq',
address@hidden(`$1', forloop(`$1', `3', `$#',
address@hidden  `$0_(`1', `2', indir(`$1'))')`popdef(
address@hidden    `$1')')indir(`$1', $@@)')
address@hidden(`_foreachq_',
address@hidden(`$$1', `$$3')$$2`''')
address@hidden'dnl
+traceon(`shift')debugmode(`aq')
address@hidden
+foreachq(`x', ``1', `2', `3', `4'', `x
+')dnl
address@hidden
address@hidden
address@hidden
 @result{}4
 @end example
 
@@ -7347,6 +7611,11 @@ foreach(`x', `(`1', `2', `3', `4')', `x
 @error{}m4trace: -3- shift(``4'')
 @end example
 
+It is likewise possible to write a variant of @code{foreach} that
+performs in linear time on M4 1.4.x; the easiest method is probably
+writing a version of @code{foreach} that unboxes its list, then invokes
address@hidden as previously defined in @file{foreachq4.m4}.
+
 In summary, recursion over list elements is trickier than it appeared at
 first glance, but provides a powerful idiom within @code{m4} processing.
 As a final demonstration, both list styles are now able to handle
@@ -7354,7 +7623,8 @@ several scenarios that would wreak havoc on one or both 
of the original
 implementations.  This points out one other difference between the
 list styles.  @code{foreach} evaluates unquoted list elements only once,
 in preparation for calling @address@hidden, similary for
address@hidden as provided by @file{foreachq3.m4}.  But
address@hidden as provided by @file{foreachq3.m4} or
address@hidden  But
 @code{foreachq}, as provided by @file{foreachq2.m4},
 evaluates unquoted list elements twice while visiting the first list
 element, once in @address@hidden and once in @address@hidden  When
@@ -7435,6 +7705,61 @@ foreachq(`x', ```active'', ``active''', `<x>
 @result{}<active>
 @end example
 
address@hidden
address@hidden Not worth putting in the manual, but make sure that foreach
address@hidden implementations behave, and that final implementation is
address@hidden linear.
+
address@hidden boxed recursion
+
address@hidden examples
address@hidden options: -Dlimit=10 -Dverbose
address@hidden
+$ @kbd {m4 -I examples -Dlimit=10 -Dverbose}
+include(`loop.m4')dnl
address@hidden 1 2 3 4 5 6 7 8 9 10
address@hidden example
+
address@hidden unboxed recursion
+
address@hidden examples
address@hidden options: -Dlimit=10 -Dverbose -Dalt
address@hidden
+$ @kbd {m4 -I examples -Dlimit=10 -Dverbose -Dalt}
+include(`loop.m4')dnl
address@hidden 1 2 3 4 5 6 7 8 9 10
address@hidden example
+
address@hidden foreach via forloop recursion
+
address@hidden examples
address@hidden options: -Dlimit=10 -Dverbose -Dalt=4
address@hidden
+$ @kbd {m4 -I examples -Dlimit=10 -Dverbose -Dalt=4}
+include(`loop.m4')dnl
address@hidden 1 2 3 4 5 6 7 8 9 10
address@hidden example
+
address@hidden examples
address@hidden options: -Dlimit=2500 -Dalt=4
address@hidden
+$ @kbd {m4 -I examples -Dlimit=2500 -Dalt=4}
+include(`loop.m4')dnl
address@hidden example
+
address@hidden examples
address@hidden options: -Dlimit=10000 -Dalt=4
address@hidden
+$ @kbd {m4 -I examples -Dlimit=10000 -Dalt=4}
+define(`foo', `divert`'len(popdef(`_foreachq')_foreachq($@@))')dnl
+define(`debug', `pushdef(`_foreachq', defn(`foo'))')
address@hidden
+include(`loop.m4')dnl
address@hidden
address@hidden example
+
address@hidden ignore
+
 @node Improved m4wrap
 @section Solution for @code{m4wrap}
 
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 6bbf4c5..a65f988 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -34,6 +34,7 @@ foreach2.m4 \
 foreachq.m4 \
 foreachq2.m4 \
 foreachq3.m4 \
+foreachq4.m4 \
 forloop.m4 \
 forloop2.m4 \
 fstab.m4 \
@@ -51,7 +52,6 @@ pushpop.m4 \
 quote.m4 \
 regexp.m4 \
 reverse.m4 \
-stackovf.sh \
 sync-lines.m4 \
 sysv-args.m4 \
 trace.m4 \
diff --git a/examples/foreachq3.m4 b/examples/foreachq3.m4
index beab455..5e65672 100644
--- a/examples/foreachq3.m4
+++ b/examples/foreachq3.m4
@@ -1,10 +1,9 @@
 divert(`-1')
 # foreachq(x, `item_1, item_2, ..., item_n', stmt)
 #   quoted list, alternate improved version
-define(`foreachq',
-`pushdef(`$1')_$0(`$1', `$3'ifelse(`$2', `', `',
-  `, $2'))popdef(`$1')')
-define(`_foreachq', `ifelse(`$#', `2', `',
-  `define(`$1', `$3')$2`'$0(`$1', `$2'ifelse(`$#', `3', `',
-    `, shift(shift(shift($@)))'))')')
+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
diff --git a/examples/foreachq4.m4 b/examples/foreachq4.m4
new file mode 100644
index 0000000..3da64c9
--- /dev/null
+++ b/examples/foreachq4.m4
@@ -0,0 +1,13 @@
+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
diff --git a/examples/forloop2.m4 b/examples/forloop2.m4
index 41e0e16..b7154e8 100644
--- a/examples/forloop2.m4
+++ b/examples/forloop2.m4
@@ -3,10 +3,10 @@ divert(`-1')
 #   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(`($3) >= ($2)'), `1',
-  `pushdef(`$1', eval(`$2'))_$0(`$1',
+define(`forloop', `ifelse(eval(`($2) <= ($3)'), `1',
+  `pushdef(`$1')_$0(`$1', eval(`$2'),
     eval(`$3'), `$4')popdef(`$1')')')
 define(`_forloop',
-  `$3`'ifelse(indir(`$1'), `$2', `',
-    `define(`$1', incr(indir(`$1')))$0($@)')')
+  `define(`$1', `$2')$4`'ifelse(`$2', `$3', `',
+    `$0(`$1', incr(`$2'), `$3', `$4')')')
 divert`'dnl
diff --git a/examples/loop.m4 b/examples/loop.m4
index 31761c9..b2fc64c 100644
--- a/examples/loop.m4
+++ b/examples/loop.m4
@@ -1,7 +1,7 @@
 dnl Stress test for recursion algorithms.  Usage:
 dnl m4 -Ipath/to/examples [-Doptions] loop.m4
 dnl Options include:
-dnl -Dalt - test with foreachq3 instead of foreachq2
+dnl -Dalt[=<n>] - test with foreachq<n> instead of foreachq2, default 3
 dnl -Dlimit=<num> - set upper limit of sequence to <num>, default 1000
 dnl -Dverbose - print the sequence to the screen, rather than discarding
 dnl -Ddebug[=<code>] - execute <code> after forloop but before foreach
@@ -9,7 +9,8 @@ dnl -Dsleep=<num> - sleep for <num> seconds before exit, to 
allow time
 dnl   to examine peak process memory usage
 include(`forloop2.m4')dnl
 include(`quote.m4')dnl
-include(ifdef(`alt', ``foreachq3.m4'', ``foreachq2.m4''))dnl
+ifelse(alt, `alt', `define(`alt', `2')', alt, `', `define(`alt', `3')')dnl
+include(`foreachq'alt`.m4')dnl
 ifdef(`limit', `', `define(`limit', `1000')')dnl
 ifdef(`verbose', `', `divert(`-1')')dnl
 ifdef(`debug', `', `define(`debug')')dnl
diff --git a/examples/stackovf.sh b/examples/stackovf.sh
deleted file mode 100644
index 8916afc..0000000
--- a/examples/stackovf.sh
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/bin/sh
-
-# Script to verify that stack overflow is diagnosed properly when
-# there is infinite macro call nesting.
-# (causes coredump in m4-1.0.3)
-
-# On some systems the ulimit command is available in ksh or bash but not sh
-(exec 2>/dev/null; ulimit -HSs 300) || {
-    for altshell in bash bsh ksh ; do
-       if (exec >/dev/null 2>&1; $altshell -c 'ulimit -HSs 300') && 
-                                                               test -z "$1" 
-       then
-               echo "Using $altshell because it supports ulimit"
-               exec $altshell $0 running-with-$altshell
-               exit 9
-       fi
-    done
-}
-
-PATH=.:..:$PATH; export PATH;
-M4=m4
-type $M4
-
-tmpfile=`tempfile 2> /dev/null` || tmpfile=/tmp/t.$$
-trap 'rm -f $tmpfile; exit 1' 1 2 3 15
-
-rm -f core
-perl -e '
-# Generate nested define sequence
-$max=1000000;
-for ($i=0; $i<$max; $i++) {
-       print "define(X$i,\n";
-}
-for ($i=$max-1; $i>=0; $i--) {
-       print "body with substance no. $i)dnl\n"
-}
-' | \
-(
-# Limit the stack size if the shell we are running permits it
-if (exec 2>/dev/null; ulimit -HSs 50)
-then
-       (exec >/dev/null 2>&1; ulimit -v) && ulimitdashv=ok
-       ulimit -HSs 50
-       #ulimit -HSd 8000
-       #test -n "$ulimitdashv" && ulimit -HSv 8000
-       echo "Stack limit is `ulimit -s`K";
-       echo "Heap limit  is `ulimit -d`K";
-       test -n "$ulimitdashv" && 
-               echo "VMem limit  is `ulimit -v`K";
-else
-       echo "Can't reset stack limit - this may take a while..."
-fi
-$M4 -L999999999 > $tmpfile 2>&1
-)
-result=$?
-
-exitcode=1
-if test $result -eq 0 ; then
-    echo "TEST DID NOT WORK - m4 did not abort.  Output:"
-else
-    # See if stack overflow was diagnosed
-    case "`cat $tmpfile`" in
-    *overflow*)
-       echo "Test succeeded."; 
-       exitcode=0
-       ;;
-    *ut*of*emory*)
-        echo "*** Test is INCONCLUSIVE (ran out of heap before stack 
overflow)";
-       ;;
-    *) echo "*** Test FAILED.  $M4 aborted unexpectedly.  Output:";
-       ;;
-    esac
-fi
-
-if test -f core ; then
-    ls -l core
-    exitcode=1
-fi
-
-#(test $exitcode -ne 0) &&
-    { echo "Output from $M4:"; cat $tmpfile; }
-
-exit $exitcode
diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4
index fc7e67a..c2d5e1e 100644
--- a/m4/gnulib-cache.m4
+++ b/m4/gnulib-cache.m4
@@ -15,11 +15,54 @@
 
 
 # Specification in the form of a command-line invocation:
-#   gnulib-tool --import --dir=. --local-dir=local --lib=libm4 
--source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=build-aux --with-tests 
--no-libtool --macro-prefix=M4 announce-gen assert avltree-oset binary-io 
clean-temp cloexec close-stream closein config-h error fdl fflush fopen-safer 
fseeko gendocs getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops 
mkstemp obstack regex stdbool stdint stdlib-safer strstr strtod strtol 
unlocked-io verror version-etc version-etc-fsf xalloc xprintf xvasprintf-posix
+#   gnulib-tool --import --dir=. --local-dir=local --lib=libm4 
--source-base=lib --m4-base=m4 --doc-base=doc --aux-dir=build-aux --with-tests 
--no-libtool --macro-prefix=M4 announce-gen assert autobuild avltree-oset 
binary-io c-stack clean-temp cloexec close-stream closein config-h error fdl 
fflush fopen-safer fseeko gendocs getopt git-version-gen gnumakefile gnupload 
gpl-3.0 intprops mkstemp obstack progname regex sigaction stdbool stdint 
stdlib-safer strsignal strstr strtod strtol unlocked-io verror version-etc 
version-etc-fsf xalloc xprintf xvasprintf-posix
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
 gl_LOCAL_DIR([local])
-gl_MODULES([announce-gen assert avltree-oset binary-io clean-temp cloexec 
close-stream closein config-h error fdl fflush fopen-safer fseeko gendocs 
getopt git-version-gen gnumakefile gnupload gpl-3.0 intprops mkstemp obstack 
regex stdbool stdint stdlib-safer strstr strtod strtol unlocked-io verror 
version-etc version-etc-fsf xalloc xprintf xvasprintf-posix])
+gl_MODULES([
+  announce-gen
+  assert
+  autobuild
+  avltree-oset
+  binary-io
+  c-stack
+  clean-temp
+  cloexec
+  close-stream
+  closein
+  config-h
+  error
+  fdl
+  fflush
+  fopen-safer
+  fseeko
+  gendocs
+  getopt
+  git-version-gen
+  gnumakefile
+  gnupload
+  gpl-3.0
+  intprops
+  mkstemp
+  obstack
+  progname
+  regex
+  sigaction
+  stdbool
+  stdint
+  stdlib-safer
+  strsignal
+  strstr
+  strtod
+  strtol
+  unlocked-io
+  verror
+  version-etc
+  version-etc-fsf
+  xalloc
+  xprintf
+  xvasprintf-posix
+])
 gl_AVOID([])
 gl_SOURCE_BASE([lib])
 gl_M4_BASE([m4])
diff --git a/src/Makefile.am b/src/Makefile.am
index f2c1524..80b9acf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,7 +24,4 @@ AM_CPPFLAGS = -I$(top_srcdir)/lib -I../lib
 bin_PROGRAMS = m4
 m4_SOURCES = m4.h m4.c builtin.c debug.c eval.c format.c freeze.c input.c \
 macro.c output.c path.c symtab.c
-if STACKOVF
-m4_SOURCES += stackovf.c
-endif
-m4_LDADD = ../lib/libm4.a $(LIBM4_LIBDEPS) $(POW_LIB)
+m4_LDADD = ../lib/libm4.a $(LIBM4_LIBDEPS) $(POW_LIB) $(LIBCSTACK)
diff --git a/src/builtin.c b/src/builtin.c
index e4d67a7..c38ed5f 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -91,8 +91,7 @@ DECLARE (m4_undivert);
 
 #undef DECLARE
 
-static builtin
-builtin_tab[] =
+static builtin const builtin_tab[] =
 {
 
   /* name              GNUext  macros  blind   function */
@@ -153,16 +152,18 @@ builtin_tab[] =
   { "placeholder",     true,   false,  false,  m4_placeholder },
 };
 
-static predefined const
-predefined_tab[] =
+static predefined const predefined_tab[] =
 {
 #if UNIX
   { "unix",    "__unix__",     "" },
-#elif W32_NATIVE
+#endif
+#if W32_NATIVE
   { "windows", "__windows__",  "" },
-#elif OS2
+#endif
+#if OS2
   { "os2",     "__os2__",      "" },
-#else
+#endif
+#if !UNIX && !W32_NATIVE && !OS2
 # warning Platform macro not provided
 #endif
   { NULL,      "__gnu__",      "" },
@@ -1562,7 +1563,9 @@ m4_traceon (struct obstack *obs, int argc, token_data 
**argv)
   else
     for (i = 1; i < argc; i++)
       {
-       s = lookup_symbol (TOKEN_DATA_TEXT (argv[i]), SYMBOL_INSERT);
+       s = lookup_symbol (ARG (i), SYMBOL_LOOKUP);
+       if (!s)
+         s = lookup_symbol (ARG (i), SYMBOL_INSERT);
        set_trace (s, obs);
       }
 }
@@ -1861,7 +1864,7 @@ m4_format (struct obstack *obs, int argc, token_data 
**argv)
 {
   if (bad_argc (argv[0], argc, 2, -1))
     return;
-  format (obs, argc - 1, argv + 1);
+  expand_format (obs, argc - 1, argv + 1);
 }
 
 /*-------------------------------------------------------------------------.
diff --git a/src/format.c b/src/format.c
index c450f0c..518394a 100644
--- a/src/format.c
+++ b/src/format.c
@@ -53,7 +53,7 @@
 `------------------------------------------------------------------*/
 
 void
-format (struct obstack *obs, int argc, token_data **argv)
+expand_format (struct obstack *obs, int argc, token_data **argv)
 {
   const char *f;                       /* format control string */
   const char *fmt;                     /* position within f */
diff --git a/src/freeze.c b/src/freeze.c
index ccdccf4..2a7ff30 100644
--- a/src/freeze.c
+++ b/src/freeze.c
@@ -56,9 +56,10 @@ produce_frozen_state (const char *name)
   symbol *sym;
   const builtin *bp;
 
-  if (file = fopen (name, O_BINARY ? "wb" : "w"), !file)
+  file = fopen (name, O_BINARY ? "wb" : "w");
+  if (!file)
     {
-      M4ERROR ((warning_status, errno, "%s", name));
+      M4ERROR ((EXIT_FAILURE, errno, "cannot open %s", name));
       return;
     }
 
@@ -186,34 +187,51 @@ reload_frozen_state (const char *name)
   int allocated[2];
   int number[2];
   const builtin *bp;
+  bool advance_line = true;
 
-#define GET_CHARACTER \
-  (character = getc (file))
+#define GET_CHARACTER                                          \
+  do                                                           \
+    {                                                          \
+      if (advance_line)                                                \
+       {                                                       \
+         current_line++;                                       \
+         advance_line = false;                                 \
+       }                                                       \
+      (character = getc (file));                               \
+      if (character == '\n')                                   \
+       advance_line = true;                                    \
+    }                                                          \
+  while (0)
 
-#define GET_NUMBER(Number) \
+#define GET_NUMBER(Number, AllowNeg)                           \
   do                                                           \
     {                                                          \
-      (Number) = 0;                                            \
-      while (isdigit (character))                              \
+      unsigned int n = 0;                                      \
+      while (isdigit (character) && n <= INT_MAX / 10)         \
        {                                                       \
-         (Number) = 10 * (Number) + character - '0';           \
+         n = 10 * n + character - '0';                         \
          GET_CHARACTER;                                        \
        }                                                       \
+      if (((AllowNeg) ? INT_MIN : INT_MAX) < n                 \
+         || isdigit (character))                               \
+       m4_error (EXIT_FAILURE, 0,                              \
+                 _("integer overflow in frozen file"));        \
+      (Number) = n;                                            \
     }                                                          \
   while (0)
 
-#define VALIDATE(Expected) \
+#define VALIDATE(Expected)                                     \
   do                                                           \
     {                                                          \
       if (character != (Expected))                             \
-       issue_expect_message ((Expected));                      \
+       issue_expect_message (Expected);                        \
     }                                                          \
   while (0)
 
   /* Skip comments (`#' at beginning of line) and blank lines, setting
      character to the next directive or to EOF.  */
 
-#define GET_DIRECTIVE \
+#define GET_DIRECTIVE                                          \
   do                                                           \
     {                                                          \
       GET_CHARACTER;                                           \
@@ -226,9 +244,35 @@ reload_frozen_state (const char *name)
     }                                                          \
   while (character == '\n')
 
+#define GET_STRING(i)                                                  \
+  do                                                                   \
+    {                                                                  \
+      void *tmp;                                                       \
+      char *p;                                                         \
+      if (number[(i)] + 1 > allocated[(i)])                            \
+       {                                                               \
+         free (string[(i)]);                                           \
+         allocated[(i)] = number[(i)] + 1;                             \
+         string[(i)] = xcharalloc ((size_t) allocated[(i)]);           \
+       }                                                               \
+      if (number[(i)] > 0                                              \
+         && !fread (string[(i)], (size_t) number[(i)], 1, file))       \
+       m4_error (EXIT_FAILURE, 0,                                      \
+                 _("premature end of frozen file"));                   \
+      string[(i)][number[(i)]] = '\0';                                 \
+      p = string[(i)];                                                 \
+      while ((tmp = memchr(p, '\n', number[(i)] - (p - string[(i)])))) \
+       {                                                               \
+         current_line++;                                               \
+         p = (char *) tmp + 1;                                         \
+       }                                                               \
+    }                                                                  \
+  while (0)
+
   file = m4_path_search (name, NULL);
   if (file == NULL)
     M4ERROR ((EXIT_FAILURE, errno, "cannot open %s", name));
+  current_file = name;
 
   allocated[0] = 100;
   string[0] = xcharalloc ((size_t) allocated[0]);
@@ -239,7 +283,7 @@ reload_frozen_state (const char *name)
   GET_DIRECTIVE;
   VALIDATE ('V');
   GET_CHARACTER;
-  GET_NUMBER (number[0]);
+  GET_NUMBER (number[0], false);
   if (number[0] > 1)
     M4ERROR ((EXIT_MISMATCH, 0,
              "frozen file version %d greater than max supported of 1",
@@ -270,49 +314,19 @@ reload_frozen_state (const char *name)
          if (operation == 'D' && character == '-')
            {
              GET_CHARACTER;
-             GET_NUMBER (number[0]);
+             GET_NUMBER (number[0], true);
              number[0] = -number[0];
            }
          else
-           GET_NUMBER (number[0]);
+           GET_NUMBER (number[0], false);
          VALIDATE (',');
          GET_CHARACTER;
-         GET_NUMBER (number[1]);
+         GET_NUMBER (number[1], false);
          VALIDATE ('\n');
 
          if (operation != 'D')
-           {
-
-             /* Get first string contents.  */
-
-             if (number[0] + 1 > allocated[0])
-               {
-                 free (string[0]);
-                 allocated[0] = number[0] + 1;
-                 string[0] = xcharalloc ((size_t) allocated[0]);
-               }
-
-             if (number[0] > 0)
-               if (!fread (string[0], (size_t) number[0], 1, file))
-                 M4ERROR ((EXIT_FAILURE, 0, "premature end of frozen file"));
-
-             string[0][number[0]] = '\0';
-           }
-
-         /* Get second string contents.  */
-
-         if (number[1] + 1 > allocated[1])
-           {
-             free (string[1]);
-             allocated[1] = number[1] + 1;
-             string[1] = xcharalloc ((size_t) allocated[1]);
-           }
-
-         if (number[1] > 0)
-           if (!fread (string[1], (size_t) number[1], 1, file))
-             M4ERROR ((EXIT_FAILURE, 0, "premature end of frozen file"));
-
-         string[1][number[1]] = '\0';
+           GET_STRING (0);
+         GET_STRING (1);
          GET_CHARACTER;
          VALIDATE ('\n');
 
@@ -372,12 +386,14 @@ reload_frozen_state (const char *name)
 
   free (string[0]);
   free (string[1]);
-  errno = 0;
-  if (ferror (file) || fclose (file) != 0)
-    M4ERROR ((EXIT_FAILURE, errno, "unable to read frozen state"));
+  if (close_stream (file) != 0)
+    m4_error (EXIT_FAILURE, errno, _("unable to read frozen state"));
+  current_file = NULL;
+  current_line = 0;
 
 #undef GET_CHARACTER
 #undef GET_DIRECTIVE
 #undef GET_NUMBER
 #undef VALIDATE
+#undef GET_STRING
 }
diff --git a/src/input.c b/src/input.c
index 7f6f87b..889a5b9 100644
--- a/src/input.c
+++ b/src/input.c
@@ -1,7 +1,7 @@
 /* GNU m4 -- A simple macro processor
 
-   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006,
+   2007, 2008 Free Software Foundation, Inc.
 
    This file is part of GNU M4.
 
@@ -169,12 +169,12 @@ static const char *token_type_string (token_type);
 | push_file () pushes an input file on the input stack, saving the   |
 | current file name and line number.  If next is non-NULL, this push |
 | invalidates a call to push_string_init (), whose storage is        |
-| consequently released.  If CLOSE, then close FP after EOF is       |
-| detected.                                                          |
+| consequently released.  If CLOSE_WHEN_DONE, then close FP after    |
+| EOF is detected.                                                   |
 `-------------------------------------------------------------------*/
 
 void
-push_file (FILE *fp, const char *title, bool close)
+push_file (FILE *fp, const char *title, bool close_when_done)
 {
   input_block *i;
 
@@ -196,7 +196,7 @@ push_file (FILE *fp, const char *title, bool close)
 
   i->u.u_f.fp = fp;
   i->u.u_f.end = false;
-  i->u.u_f.close = close;
+  i->u.u_f.close = close_when_done;
   i->u.u_f.advance = start_of_input_line;
   output_current_line = -1;
 
diff --git a/src/m4.c b/src/m4.c
index fb10908..6abd3e1 100644
--- a/src/m4.c
+++ b/src/m4.c
@@ -1,7 +1,7 @@
 /* GNU m4 -- A simple macro processor
 
-   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006, 2007
-   Free Software Foundation, Inc.
+   Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 2004, 2005, 2006,
+   2007, 2008 Free Software Foundation, Inc.
 
    This file is part of GNU M4.
 
@@ -25,6 +25,8 @@
 #include <limits.h>
 #include <signal.h>
 
+#include "c-stack.h"
+#include "progname.h"
 #include "version-etc.h"
 
 #define AUTHORS "Rene' Seindal"
@@ -66,9 +68,6 @@ int nesting_limit = 1024;
 const char *user_word_regexp = "";
 #endif
 
-/* The name this program was run with. */
-const char *program_name;
-
 /* Global catchall for any errors that should affect final error status, but
    where we try to continue execution in the meantime.  */
 int retcode;
@@ -113,20 +112,52 @@ m4_error_at_line (int status, int errnum, const char 
*file, int line,
     retcode = EXIT_FAILURE;
 }
 
-#ifdef USE_STACKOVF
+#ifndef SIGBUS
+# define SIGBUS SIGILL
+#endif
 
-/*---------------------------------------.
-| Tell user stack overflowed and abort.         |
-`---------------------------------------*/
+#ifndef NSIG
+# ifndef MAX
+#  define MAX(a,b) ((a) < (b) ? (b) : (a))
+# endif
+# define NSIG (MAX (SIGABRT, MAX (SIGILL, MAX (SIGFPE,  \
+                                               MAX (SIGSEGV, SIGBUS)))) + 1)
+#endif
 
+/* Pre-translated messages for program errors.  Do not translate in
+   the signal handler, since gettext and strsignal are not
+   async-signal-safe.  */
+static const char * volatile program_error_message;
+static const char * volatile signal_message[NSIG];
+
+/* Print a nicer message about any programmer errors, then exit.  This
+   must be aysnc-signal safe, since it is executed as a signal
+   handler.  If SIGNO is zero, this represents a stack overflow; in
+   that case, we return to allow c_stack_action to handle things.  */
 static void
-stackovf_handler (void)
+fault_handler (int signo)
 {
-  M4ERROR ((EXIT_FAILURE, 0,
-           "ERROR: stack overflow.  (Infinite define recursion?)"));
+  if (signo)
+    {
+      /* POSIX states that reading static memory is, in general, not
+         async-safe.  However, the static variables that we read are
+         never modified once this handler is installed, so this
+         particular usage is safe.  And it seems an oversight that
+         POSIX claims strlen is not async-safe.  */
+      write (STDERR_FILENO, program_name, strlen (program_name));
+      write (STDERR_FILENO, ": ", 2);
+      write (STDERR_FILENO, program_error_message,
+             strlen (program_error_message));
+      if (signal_message[signo])
+        {
+          write (STDERR_FILENO, ": ", 2);
+          write (STDERR_FILENO, signal_message[signo],
+                 strlen (signal_message[signo]));
+        }
+      write (STDERR_FILENO, "\n", 1);
+      _exit (EXIT_INTERNAL_ERROR);
+    }
 }
-
-#endif /* USE_STACKOV */
 
 
 /*---------------------------------------------.
@@ -177,15 +208,16 @@ Preprocessor features:\n\
   -s, --synclines              generate `#line NUM \"FILE\"' lines\n\
   -U, --undefine=NAME          undefine NAME\n\
 ", stdout);
-      fputs ("\
-\n\
+      puts ("");
+      xprintf (_("\
 Limits control:\n\
+  -g, --gnu                    override -G to re-enable GNU extensions\n\
   -G, --traditional            suppress all GNU extensions\n\
   -H, --hashsize=PRIME         set symbol lookup hash table size [509]\n\
-  -L, --nesting-limit=NUMBER   change artificial nesting limit [1024]\n\
-", stdout);
+  -L, --nesting-limit=NUMBER   change nesting limit, 0 for unlimited [%d]\n\
+"), nesting_limit);
+      puts ("");
       fputs ("\
-\n\
 Frozen state files:\n\
   -F, --freeze-state=FILE      produce a frozen state on FILE at end\n\
   -R, --reload-state=FILE      reload a frozen state from FILE at start\n\
@@ -252,6 +284,7 @@ static const struct option long_options[] =
   {"error-output", required_argument, NULL, 'o'}, /* FIXME: deprecate in 2.0 */
   {"fatal-warnings", no_argument, NULL, 'E'},
   {"freeze-state", required_argument, NULL, 'F'},
+  {"gnu", no_argument, NULL, 'g'},
   {"hashsize", required_argument, NULL, 'H'},
   {"include", required_argument, NULL, 'I'},
   {"interactive", no_argument, NULL, 'i'},
@@ -313,14 +346,15 @@ process_file (const char *name)
    '-' forces getopt_long to hand back file names as arguments to opt
    '\1', rather than reordering the command line.  */
 #ifdef ENABLE_CHANGEWORD
-#define OPTSTRING "-B:D:EF:GH:I:L:N:PQR:S:T:U:W:d::eil:o:st:"
+#define OPTSTRING "-B:D:EF:GH:I:L:N:PQR:S:T:U:W:d::egil:o:st:"
 #else
-#define OPTSTRING "-B:D:EF:GH:I:L:N:PQR:S:T:U:d::eil:o:st:"
+#define OPTSTRING "-B:D:EF:GH:I:L:N:PQR:S:T:U:d::egil:o:st:"
 #endif
 
 int
 main (int argc, char *const *argv, char *const *envp)
 {
+  struct sigaction act;
   macro_definition *head;      /* head of deferred argument list */
   macro_definition *tail;
   macro_definition *defn;
@@ -334,18 +368,54 @@ main (int argc, char *const *argv, char *const *envp)
   const char *frozen_file_to_write = NULL;
   const char *macro_sequence = "";
 
-  program_name = argv[0];
+  set_program_name (argv[0]);
   retcode = EXIT_SUCCESS;
   atexit (close_stdin);
 
   include_init ();
   debug_init ();
-#ifdef USE_STACKOVF
-  setup_stackovf_trap (argv, envp, stackovf_handler);
-#endif
 
-  /* First, we decode the arguments, to size up tables and stuff.  */
+  /* 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;
+  program_error_message
+    = xasprintf (_("internal error detected; please report this bug to <%s>"),
+                 PACKAGE_BUGREPORT);
+  signal_message[SIGSEGV] = xstrdup (strsignal (SIGSEGV));
+  signal_message[SIGABRT] = xstrdup (strsignal (SIGABRT));
+  signal_message[SIGILL] = xstrdup (strsignal (SIGILL));
+  signal_message[SIGFPE] = xstrdup (strsignal (SIGFPE));
+  if (SIGBUS != SIGILL)
+    signal_message[SIGBUS] = xstrdup (strsignal (SIGBUS));
+  sigemptyset (&act.sa_mask);
+  /* One-shot - if we fault while handling a fault, we want to revert
+     to default signal behavior.  */
+  act.sa_flags = SA_NODEFER | SA_RESETHAND;
+  act.sa_handler = fault_handler;
+  sigaction (SIGABRT, &act, NULL);
+  sigaction (SIGILL, &act, NULL);
+  sigaction (SIGFPE, &act, NULL);
+  sigaction (SIGBUS, &act, NULL);
+
+#ifdef DEBUG_STKOVF
+  /* Make it easier to test our fault handlers.  Exporting M4_CRASH=0
+     attempts a SIGSEGV, exporting it as 1 attempts an assertion
+     failure with a fallback to abort.  */
+  {
+    char *crash = getenv ("M4_CRASH");
+    if (crash)
+      {
+        if (!atoi (crash))
+          ++*(int *) 8;
+        assert (false);
+        abort ();
+      }
+  }
+#endif /* DEBUG_STKOVF */
 
+  /* First, we decode the arguments, to size up tables and stuff.  */
   head = tail = NULL;
 
   while ((optchar = getopt_long (argc, (char **) argv, OPTSTRING,
@@ -454,6 +524,10 @@ main (int argc, char *const *argv, char *const *envp)
        interactive = true;
        break;
 
+      case 'g':
+       no_gnu_extensions = 0;
+       break;
+
       case 'l':
        max_debug_argument_length = atoi (optarg);
        if (max_debug_argument_length <= 0)
diff --git a/src/m4.h b/src/m4.h
index 018e552..3bdbdca 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -27,6 +27,7 @@
 
 #include <ctype.h>
 #include <errno.h>
+#include <limits.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <string.h>
@@ -64,10 +65,17 @@
 /* Canonicalize OS/2 recognition macro.  */
 #ifdef __EMX__
 # define OS2 1
+# undef UNIX
 #endif
 
+/* Used if any programmer error is detected (not possible, right?)  */
+#define EXIT_INTERNAL_ERROR 2
+
 /* Used for version mismatch, when -R detects a frozen file it can't parse.  */
 #define EXIT_MISMATCH 63
+
+/* No-op, for future gettext compatibility.  */
+#define _(ARG) ARG
 
 /* Various declarations.  */
 
@@ -134,10 +142,6 @@ void m4_error_at_line (int, int, const char *, int,
 #define M4ERROR(Arglist) (m4_error Arglist)
 #define M4ERROR_AT_LINE(Arglist) (m4_error_at_line Arglist)
 
-#ifdef USE_STACKOVF
-void setup_stackovf_trap (char *const *, char *const *,
-                         void (*handler) (void));
-#endif
 
 /* File: debug.c  --- debugging and tracing function.  */
 
@@ -441,7 +445,7 @@ bool evaluate (const char *, int32_t *);
 
 /* File: format.c  --- printf like formatting.  */
 
-void format (struct obstack *, int, token_data **);
+void expand_format (struct obstack *, int, token_data **);
 
 /* File: freeze.c --- frozen state files.  */
 
diff --git a/src/output.c b/src/output.c
index d5f6194..d621c4b 100644
--- a/src/output.c
+++ b/src/output.c
@@ -122,10 +122,10 @@ cmp_diversion_CB (const void *elt1, const void *elt2)
 static bool
 threshold_diversion_CB (const void *elt, const void *threshold)
 {
-  const m4_diversion *div = (const m4_diversion *) elt;
+  const m4_diversion *diversion = (const m4_diversion *) elt;
   /* No need to worry about overflow, since we don't create diversions
      with negative divnum.  */
-  return div->divnum >= *(const int *) threshold;
+  return diversion->divnum >= *(const int *) threshold;
 }
 
 void
diff --git a/src/stackovf.c b/src/stackovf.c
deleted file mode 100644
index 3877cd9..0000000
--- a/src/stackovf.c
+++ /dev/null
@@ -1,422 +0,0 @@
-/* Detect stack overflow (when getrlimit and sigaction or sigvec are available)
-
-   Copyright (C) 1993, 1994, 2006, 2007 Free Software Foundation, Inc.
-   Jim Avera <address@hidden>, October 1993.
-
-   This file is part of GNU M4.
-
-   GNU M4 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.
-
-   GNU M4 is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* Compiled only when USE_STACKOVF is defined, which itself requires
-   getrlimit with the RLIMIT_STACK option, and support for alternate
-   signal stacks using either SVR4 or BSD interfaces.
-
-   This should compile on ANY system which supports either sigaltstack()
-   or sigstack(), with or without <siginfo.h> or another way to determine
-   the fault address.
-
-   There is no completely portable way to determine if a SIGSEGV signal
-   indicates a stack overflow.  The fault address can be used to infer
-   this.  However, the fault address is passed to the signal handler in
-   different ways on various systems.  One of three methods are used to
-   determine the fault address:
-
-      1. The siginfo parameter (with siginfo.h, i.e., SVR4).
-
-      2. 4th "addr" parameter (assumed if struct sigcontext is defined,
-        i.e., SunOS 4.x/BSD).
-
-      3. None (if no method is available).  This case just prints a
-      message before aborting with a core dump.  That way the user at
-      least knows that it *might* be a recursion problem.
-
-   Jim Avera <address@hidden> writes, on Tue, 5 Oct 93 19:27 PDT:
-
-      "I got interested finding out how a program could catch and
-      diagnose its own stack overflow, and ended up modifying m4 to do
-      this.  Now it prints a nice error message and exits.
-
-      How it works: SIGSEGV is caught using a separate signal stack.  The
-      signal handler declares a stack overflow if the fault address is
-      near the end of the stack region, or if the maximum VM address
-      space limit has been reached.  Otherwise, it returns to re-execute
-      the instruction with SIG_DFL set, so that any real bugs cause a
-      core dump as usual."
-
-   Jim Avera <address@hidden> writes, on Fri, 24 Jun 94 12:14 PDT:
-
-      "The stack-overflow detection code would still be needed to avoid a
-      SIGSEGV abort if swap space was exhausted at the moment the stack
-      tried to grow.  This is probably unlikely to occur with the
-      explicit nesting limit option of GNU m4."
-
-   Jim Avera <address@hidden> writes, on Wed, 6 Jul 1994 14:41 PDT:
-
-      "When a stack overflow occurs, a SIGSEGV signal is sent, which by
-      default aborts the process with a core dump.
-
-      The code in stackovf.c catches SIGSEGV using a separate signal
-      stack.  The signal handler determines whether or not the SIGSEGV
-      arose from a stack overflow.  If it is a stack overflow, an
-      external function is called (which, in m4, prints a message an
-      exits).  Otherwise the SIGSEGV represents an m4 bug, and the signal
-      is re-raised with SIG_DFL set, which results in an abort and core
-      dump in the usual way.  It seems important (to me) that internal m4
-      bugs not be reported as user recursion errors, or vice-versa."  */
-
-#include "m4.h"                        /* stdlib.h, xmalloc() */
-
-#include <assert.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <signal.h>
-
-#if HAVE_SIGINFO_H
-# include <siginfo.h>
-#endif
-
-#ifndef SA_RESETHAND
-# define SA_RESETHAND 0
-#endif
-#ifndef SA_SIGINFO
-# define SA_SIGINFO 0
-#endif
-
-#ifndef SIGSTKSZ
-# define SIGSTKSZ 8192
-#endif
-
-/* If the trap address is within STACKOVF_DETECT bytes of the calculated
-   stack limit, we diagnose a stack overflow.  This must be large enough
-   to cover errors in our estimatation of the limit address, and to
-   account for the maximum size of local variables (the amount the
-   trapping reference might exceed the stack limit).  Also, some machines
-   may report an arbitrary address within the same page frame.
-   If the value is too large, we might call some other SIGSEGV a stack
-   overflow, masking a bug.  */
-
-#ifndef STACKOVF_DETECT
-# define STACKOVF_DETECT 16384
-#endif
-
-typedef void (*handler_t) (void);
-
-static const char *stackbot;
-static const char *stackend;
-static const char *arg0;
-static handler_t stackovf_handler;
-
-/* The following OS-independent procedure is called from the SIGSEGV
-   signal handler.  The signal handler obtains information about the trap
-   in an OS-dependent manner, and passes a parameter with the meanings as
-   explained below.
-
-   If the OS explicitly identifies a stack overflow trap, either pass
-   PARAM_STACKOVF if a stack overflow, or pass PARAM_NOSTACKOVF if not
-   (id est, it is a random bounds violation).  Otherwise, if the fault
-   address is available, pass the fault address.  Otherwise (if no
-   information is available), pass NULL.
-
-   Not given an explicit indication, we compare the fault address with
-   the estimated stack limit, and test to see if overall VM space is
-   exhausted.
-
-   If a stack overflow is identified, then the external *stackovf_handler
-   function is called, which should print an error message and exit.  If
-   it is NOT a stack overflow, then we silently abort with a core dump by
-   returning to re-raise the SIGSEGV with SIG_DFL set.  If indeterminate,
-   then we do not call *stackovf_handler, but instead print an ambiguous
-   message and abort with a core dump.  This only occurs on systems which
-   provide no information, but is better than nothing.  */
-
-#define PARAM_STACKOVF ((const char *) (1 + STACKOVF_DETECT))
-#define PARAM_NOSTACKOVF ((const char *) (2 + STACKOVF_DETECT))
-
-static void
-process_sigsegv (int signo, const char *p)
-{
-  long diff;
-  diff = (p - stackend);
-
-#ifdef DEBUG_STKOVF
-  {
-    char buf[140];
-
-    snprintf (buf, sizeof buf,
-              "process_sigsegv: p=%#lx stackend=%#lx diff=%ld bot=%#lx\n",
-              (long) p, (long) stackend, (long) diff, (long) stackbot);
-    write (2, buf, strlen (buf));
-  }
-#endif
-
-  if (p != PARAM_NOSTACKOVF)
-    {
-      if ((long) sbrk (8192) == (long) -1)
-       {
-
-         /* sbrk failed.  Assume the RLIMIT_VMEM prevents expansion even
-            if the stack limit has not been reached.  */
-
-         write (2, "VMEM limit exceeded?\n", 21);
-         p = PARAM_STACKOVF;
-       }
-      if (diff >= -STACKOVF_DETECT && diff <= STACKOVF_DETECT)
-       {
-
-         /* The fault address is "sufficiently close" to the stack lim.  */
-
-         p = PARAM_STACKOVF;
-       }
-      if (p == PARAM_STACKOVF)
-       {
-
-         /* We have determined that this is indeed a stack overflow.  */
-
-         (*stackovf_handler) ();       /* should call exit() */
-       }
-    }
-  if (p == NULL)
-    {
-      const char *cp;
-
-      cp = "\
-Memory bounds violation detected (SIGSEGV).  Either a stack overflow\n\
-occurred, or there is a bug in ";
-      write (2, cp, strlen (cp));
-      write (2, arg0, strlen (arg0));
-      cp = ".  Check for possible infinite recursion.\n";
-      write (2, cp, strlen (cp));
-    }
-
-  /* Return to re-execute the instruction which caused the trap with
-     SIGSEGV set to SIG_DFL.  An abort with core dump should occur.  */
-
-  signal (signo, SIG_DFL);
-}
-
-#if HAVE_STRUCT_SIGACTION_SA_SIGACTION
-
-/* POSIX.  */
-
-static void
-sigsegv_handler (int signo, siginfo_t *ip, void *context)
-{
-  process_sigsegv
-    (signo, (ip != NULL
-            && ip->si_signo == SIGSEGV ? (char *) ip->si_addr : NULL));
-}
-
-#elif HAVE_SIGINFO_T
-
-/* SVR4.  */
-
-static void
-sigsegv_handler (int signo, siginfo_t *ip)
-{
-  process_sigsegv
-    (signo, (ip != NULL
-            && ip->si_signo == SIGSEGV ? (char *) ip->si_addr : NULL));
-}
-
-#elif HAVE_SIGCONTEXT
-
-/* SunOS 4.x (and BSD?).  (not tested) */
-
-static void
-sigsegv_handler (int signo, int code, struct sigcontext *scp, char *addr)
-{
-  process_sigsegv (signo, addr);
-}
-
-#else /* not HAVE_SIGCONTEXT */
-
-/* OS provides no information.  */
-
-static void
-sigsegv_handler (int signo)
-{
-  process_sigsegv (signo, NULL);
-}
-
-#endif /* not HAVE_SIGCONTEXT */
-
-/* Arrange to trap a stack-overflow and call a specified handler.  The
-   call is on a dedicated signal stack.
-
-   argv and envp are as passed to main().
-
-   If a stack overflow is not detected, then the SIGSEGV is re-raised
-   with action set to SIG_DFL, causing an abort and coredump in the usual
-   way.
-
-   Detection of a stack overflow depends on the trap address being near
-   the stack limit address.  The stack limit can not be directly
-   determined in a portable way, but we make an estimate based on the
-   address of the argv and environment vectors, their contents, and the
-   maximum stack size obtained using getrlimit.  */
-
-void
-setup_stackovf_trap (char *const *argv, char *const *envp, handler_t handler)
-{
-  struct rlimit rl;
-  rlim_t stack_len;
-  int grows_upward;
-  register char *const *v;
-  register char *p;
-#if HAVE_SIGACTION && defined SA_ONSTACK
-  struct sigaction act;
-#elif HAVE_SIGVEC && defined SV_ONSTACK
-  struct sigvec vec;
-#else
-
-Error - Do not know how to set up stack-ovf trap handler...
-
-#endif
-
-  arg0 = argv[0];
-  stackovf_handler = handler;
-
-  /* Calculate the approximate expected addr for a stack-ovf trap.  */
-
-  if (getrlimit (RLIMIT_STACK, &rl) < 0)
-    error (EXIT_FAILURE, errno, "getrlimit");
-  stack_len = (rl.rlim_cur < rl.rlim_max ? rl.rlim_cur : rl.rlim_max);
-  stackbot = (char *) argv;
-  grows_upward = ((char *) &stack_len > stackbot);
-  if (grows_upward)
-    {
-
-      /* Grows toward increasing addresses.  */
-
-      for (v = argv; (p = (char *) *v) != NULL; v++)
-       {
-         if (p < stackbot)
-           stackbot = p;
-       }
-      if ((char *) envp < stackbot)
-       stackbot = (char *) envp;
-      for (v = envp; (p = (char *) *v) != NULL; v++)
-       {
-         if (p < stackbot)
-           stackbot = p;
-       }
-      stackend = stackbot + stack_len;
-    }
-  else
-    {
-
-      /* The stack grows "downward" (toward decreasing addresses).  */
-
-      for (v = argv; (p = (char *) *v) != NULL; v++)
-       {
-         if (p > stackbot)
-           stackbot = p;
-       }
-      if ((char *) envp > stackbot)
-       stackbot = (char *) envp;
-      for (v = envp; (p = (char *) *v) != NULL; v++)
-       {
-         if (p > stackbot)
-           stackbot = p;
-       }
-      stackend = stackbot - stack_len;
-    }
-
-  /* Allocate a separate signal-handler stack.  */
-
-#if HAVE_SIGALTSTACK && (HAVE_SIGINFO_T || ! HAVE_SIGSTACK)
-
-  /* Use sigaltstack only if siginfo_t is available, unless there is no
-     choice.  */
-
-  {
-    stack_t ss;
-# ifndef HAVE_STACK_T_SS_SP
-    /* This workaround is for BSD/OS 4.0.1:
-       http://lists.gnu.org/archive/html/bug-m4/2006-12/msg00004.html  */
-#  define ss_sp ss_base
-# endif
-
-    ss.ss_size = SIGSTKSZ;
-    ss.ss_sp = xmalloc ((unsigned) ss.ss_size);
-    ss.ss_flags = 0;
-    if (sigaltstack (&ss, NULL) < 0)
-      {
-       /* Oops - sigaltstack exists but doesn't work.  We can't
-          install the overflow detector, but should gracefully treat
-          it as though sigaltstack doesn't exist.  For example, this
-          happens when compiled with Linux 2.1 headers but run
-          against Linux 2.0 kernel.  */
-       free (ss.ss_sp);
-       if (errno == ENOSYS)
-         return;
-       error (EXIT_FAILURE, errno, "sigaltstack");
-      }
-  }
-
-#elif HAVE_SIGSTACK
-
-  {
-    struct sigstack ss;
-    char *stackbuf = xmalloc (2 * SIGSTKSZ);
-
-    ss.ss_sp = stackbuf + SIGSTKSZ;
-    ss.ss_onstack = 0;
-    if (sigstack (&ss, NULL) < 0)
-      {
-       /* Oops - sigstack exists but doesn't work.  We can't install
-          the overflow detector, but should gracefully treat it as
-          though sigstack doesn't exist.  For example, this happens
-          when compiled with Linux 2.1 headers but run against Linux
-          2.0 kernel.  */
-       free (stackbuf);
-       if (errno == ENOSYS)
-         return;
-       error (EXIT_FAILURE, errno, "sigstack");
-      }
-  }
-
-#else /* not HAVE_SIGSTACK */
-
-Error - Do not know how to set up stack-ovf trap handler...
-
-#endif /* not HAVE_SIGSTACK */
-
-  /* Arm the SIGSEGV signal handler.  */
-
-#if HAVE_SIGACTION && defined SA_ONSTACK
-
-  sigaction (SIGSEGV, NULL, &act);
-# if HAVE_STRUCT_SIGACTION_SA_SIGACTION
-  act.sa_sigaction = sigsegv_handler;
-# else /* ! HAVE_STRUCT_SIGACTION_SA_SIGACTION */
-  act.sa_handler = (RETSIGTYPE (*) (int)) sigsegv_handler;
-# endif /* ! HAVE_STRUCT_SIGACTION_SA_SIGACTION */
-  sigemptyset (&act.sa_mask);
-  act.sa_flags = (SA_ONSTACK | SA_RESETHAND | SA_SIGINFO);
-  if (sigaction (SIGSEGV, &act, NULL) < 0)
-    error (EXIT_FAILURE, errno, "sigaction");
-
-#else /* ! HAVE_SIGACTION */
-
-  vec.sv_handler = (RETSIGTYPE (*) (int)) sigsegv_handler;
-  vec.sv_mask = 0;
-  vec.sv_flags = (SV_ONSTACK | SV_RESETHAND);
-  if (sigvec (SIGSEGV, &vec, NULL) < 0)
-    error (EXIT_FAILURE, errno, "sigvec");
-
-#endif /* ! HAVE_SIGACTION */
-
-}


hooks/post-receive
--
GNU M4 source repository




reply via email to

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