From 0b98fb45910bba58a0a64192443b1d71fbf19ecf Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 7 May 2021 14:47:04 -0500 Subject: maint: Redirect developers to active branch _This_ branch does not contain actively-developed code. More likely, you want to check out branch-1.4 (latest stable), branch-1.6 (some speedups over 1.4, but not yet released), or branch-2.0 (many more experimental changes, and even further from release). * README: Document the status of this git repository. --- .autom4te.cfg | 4 - .gitattributes | 5 - .gitignore | 91 - .gitmodules | 3 - .prev-version | 1 - .x-update-copyright | 1 - AUTHORS | 43 - COPYING | 674 -- ChangeLog.old | 12324 -------------------------------- HACKING | 334 - Makefile.am | 453 -- NEWS | 1228 ---- NO-THANKS | 186 - README | 90 +- TODO | 150 - bootstrap | 5100 ------------- bootstrap.conf | 160 - build-aux/gl/build-aux/bootstrap.in | 2769 ------- build-aux/gl/build-aux/extract-trace | 420 -- build-aux/gl/build-aux/funclib.sh | 1304 ---- build-aux/gl/build-aux/inline-source | 164 - build-aux/gl/build-aux/options-parser | 608 -- build-aux/gl/lib/clean-temp.c.diff | 14 - build-aux/gnulib | 1 - build-aux/m4/debug.m4 | 94 - build-aux/m4/gmp.m4 | 77 - build-aux/m4/gnulib-cache.m4 | 120 - build-aux/m4/m4-error.m4 | 41 - build-aux/m4/m4-getopt.m4 | 35 - build-aux/m4/m4-gettext.m4 | 35 - build-aux/m4/m4-obstack.m4 | 50 - build-aux/m4/m4-regex.m4 | 39 - build-aux/m4/m4-rename.m4 | 46 - build-aux/m4/m4-syscmd.m4 | 60 - build-aux/m4/stackovf.m4 | 91 - build-aux/thanks-gen | 20 - cfg.mk | 63 - configure.ac | 362 - doc/Makefile.am | 38 - doc/STYLE | 100 - doc/examples/COPYING | 8 - doc/examples/WWW/COPYING | 8 - doc/examples/WWW/Makefile | 45 - doc/examples/WWW/_footer.htm | 10 - doc/examples/WWW/_header.htm | 231 - doc/examples/WWW/m4lib/COPYING | 8 - doc/examples/WWW/m4lib/bugs.m4 | 53 - doc/examples/WWW/m4lib/changelog.m4 | 18 - doc/examples/WWW/m4lib/download.m4 | 24 - doc/examples/WWW/m4lib/features.m4 | 58 - doc/examples/WWW/m4lib/feedback.m4 | 20 - doc/examples/WWW/m4lib/html.m4 | 122 - doc/examples/WWW/m4lib/index.m4 | 36 - doc/examples/WWW/m4lib/layout.m4 | 65 - doc/examples/WWW/m4lib/lists.m4 | 32 - doc/examples/WWW/m4lib/menu.m4 | 74 - doc/examples/WWW/m4lib/modules.m4 | 18 - doc/examples/WWW/m4lib/news.m4 | 18 - doc/examples/WWW/m4lib/readme.m4 | 18 - doc/examples/WWW/m4lib/setup.m4 | 7 - doc/examples/WWW/m4lib/test.m4 | 29 - doc/examples/WWW/m4lib/thanks.m4 | 18 - doc/examples/WWW/m4lib/thissite.m4 | 42 - doc/examples/WWW/m4lib/tmpl.m4 | 11 - doc/examples/WWW/m4lib/todo.m4 | 18 - doc/examples/WWW/m4lib/uses.m4 | 43 - doc/examples/WWW/m4lib/visions.m4 | 232 - doc/examples/WWW/m4lib/whatis.m4 | 48 - doc/examples/capitalize.m4 | 12 - doc/examples/capitalize2.m4 | 19 - doc/examples/comments.m4 | 7 - doc/examples/curry.m4 | 7 - doc/examples/ddivert.m4 | 4 - doc/examples/debug.m4 | 4 - doc/examples/esyscmd.m4 | 6 - doc/examples/exp.m4 | 3 - doc/examples/foreach.m4 | 8 - doc/examples/foreach2.m4 | 10 - doc/examples/foreachq.m4 | 9 - doc/examples/foreachq2.m4 | 10 - doc/examples/foreachq3.m4 | 9 - doc/examples/foreachq4.m4 | 13 - doc/examples/forloop.m4 | 6 - doc/examples/forloop2.m4 | 12 - doc/examples/forloop3.m4 | 13 - doc/examples/fstab.m4 | 6 - doc/examples/hanoi.m4 | 17 - doc/examples/incl-test.m4 | 3 - doc/examples/incl.m4 | 3 - doc/examples/include.m4 | 7 - doc/examples/indir.m4 | 10 - doc/examples/join.m4 | 15 - doc/examples/loop.m4 | 18 - doc/examples/misc.m4 | 8 - doc/examples/modtest.m4 | 8 - doc/examples/multiquotes.m4 | 17 - doc/examples/patsubst.m4 | 8 - doc/examples/pushpop.m4 | 25 - doc/examples/quote.m4 | 9 - doc/examples/regexp.m4 | 12 - doc/examples/reverse.m4 | 4 - doc/examples/shadow.m4 | 58 - doc/examples/stack.m4 | 16 - doc/examples/stack_sep.m4 | 17 - doc/examples/stdlib.m4 | 45 - doc/examples/sysv-args.m4 | 14 - doc/examples/time.m4 | 21 - doc/examples/time2.m4 | 19 - doc/examples/trace.m4 | 30 - doc/examples/translit.m4 | 8 - doc/examples/undivert.incl | 1 - doc/examples/undivert.m4 | 5 - doc/examples/wrap.m4 | 10 - doc/examples/wrapfifo.m4 | 10 - doc/examples/wraplifo.m4 | 10 - doc/examples/wraplifo2.m4 | 9 - doc/m4.texi | 10411 --------------------------- m4/builtin.c | 123 - m4/debug.c | 260 - m4/hash.c | 671 -- m4/hash.h | 81 - m4/input.c | 2223 ------ m4/m4.c | 159 - m4/m4module.h | 556 -- m4/m4private.h | 626 -- m4/macro.c | 1784 ----- m4/module.c | 344 - m4/output.c | 1119 --- m4/path.c | 414 -- m4/resyntax.c | 127 - m4/symtab.c | 968 --- m4/syntax.c | 954 --- m4/system_.h | 173 - m4/utility.c | 292 - modules/evalparse.c | 1029 --- modules/format.c | 425 -- modules/gnu.c | 1077 --- modules/m4.c | 1324 ---- modules/m4.h | 53 - modules/mpeval.c | 453 -- modules/stdlib.c | 288 - modules/time.c | 240 - modules/traditional.c | 52 - po/Makevars | 44 - po/POTFILES.in | 31 - src/freeze.c | 1000 --- src/m4.h | 43 - src/main.c | 762 -- src/stackovf.c | 454 -- tests/atlocal.in | 27 - tests/builtins.at | 1325 ---- tests/freeze.at | 539 -- tests/generate.awk | 216 - tests/import.c | 110 - tests/iso8859.m4 | Bin 1465 -> 0 bytes tests/m4.in | 46 - tests/macros.at | 589 -- tests/modtest.c | 101 - tests/modules.at | 344 - tests/null.err | Bin 3639 -> 0 bytes tests/null.m4 | Bin 7738 -> 0 bytes tests/null.out | Bin 631 -> 0 bytes tests/options.at | 863 --- tests/others.at | 980 --- tests/shadow.c | 91 - tests/stackovf.test | 105 - tests/testsuite.at | 180 - 167 files changed, 9 insertions(+), 63374 deletions(-) delete mode 100644 .autom4te.cfg delete mode 100644 .gitattributes delete mode 100644 .gitignore delete mode 100644 .gitmodules delete mode 100644 .prev-version delete mode 100644 .x-update-copyright delete mode 100644 AUTHORS delete mode 100644 COPYING delete mode 100644 ChangeLog.old delete mode 100644 HACKING delete mode 100644 Makefile.am delete mode 100644 NEWS delete mode 100644 NO-THANKS delete mode 100644 TODO delete mode 100755 bootstrap delete mode 100644 bootstrap.conf delete mode 100755 build-aux/gl/build-aux/bootstrap.in delete mode 100755 build-aux/gl/build-aux/extract-trace delete mode 100644 build-aux/gl/build-aux/funclib.sh delete mode 100755 build-aux/gl/build-aux/inline-source delete mode 100644 build-aux/gl/build-aux/options-parser delete mode 100644 build-aux/gl/lib/clean-temp.c.diff delete mode 160000 build-aux/gnulib delete mode 100644 build-aux/m4/debug.m4 delete mode 100644 build-aux/m4/gmp.m4 delete mode 100644 build-aux/m4/gnulib-cache.m4 delete mode 100644 build-aux/m4/m4-error.m4 delete mode 100644 build-aux/m4/m4-getopt.m4 delete mode 100644 build-aux/m4/m4-gettext.m4 delete mode 100644 build-aux/m4/m4-obstack.m4 delete mode 100644 build-aux/m4/m4-regex.m4 delete mode 100644 build-aux/m4/m4-rename.m4 delete mode 100644 build-aux/m4/m4-syscmd.m4 delete mode 100644 build-aux/m4/stackovf.m4 delete mode 100755 build-aux/thanks-gen delete mode 100644 cfg.mk delete mode 100644 configure.ac delete mode 100644 doc/Makefile.am delete mode 100644 doc/STYLE delete mode 100644 doc/examples/COPYING delete mode 100644 doc/examples/WWW/COPYING delete mode 100644 doc/examples/WWW/Makefile delete mode 100644 doc/examples/WWW/_footer.htm delete mode 100644 doc/examples/WWW/_header.htm delete mode 100644 doc/examples/WWW/m4lib/COPYING delete mode 100644 doc/examples/WWW/m4lib/bugs.m4 delete mode 100644 doc/examples/WWW/m4lib/changelog.m4 delete mode 100644 doc/examples/WWW/m4lib/download.m4 delete mode 100644 doc/examples/WWW/m4lib/features.m4 delete mode 100644 doc/examples/WWW/m4lib/feedback.m4 delete mode 100644 doc/examples/WWW/m4lib/html.m4 delete mode 100644 doc/examples/WWW/m4lib/index.m4 delete mode 100644 doc/examples/WWW/m4lib/layout.m4 delete mode 100644 doc/examples/WWW/m4lib/lists.m4 delete mode 100644 doc/examples/WWW/m4lib/menu.m4 delete mode 100644 doc/examples/WWW/m4lib/modules.m4 delete mode 100644 doc/examples/WWW/m4lib/news.m4 delete mode 100644 doc/examples/WWW/m4lib/readme.m4 delete mode 100644 doc/examples/WWW/m4lib/setup.m4 delete mode 100644 doc/examples/WWW/m4lib/test.m4 delete mode 100644 doc/examples/WWW/m4lib/thanks.m4 delete mode 100644 doc/examples/WWW/m4lib/thissite.m4 delete mode 100644 doc/examples/WWW/m4lib/tmpl.m4 delete mode 100644 doc/examples/WWW/m4lib/todo.m4 delete mode 100644 doc/examples/WWW/m4lib/uses.m4 delete mode 100644 doc/examples/WWW/m4lib/visions.m4 delete mode 100644 doc/examples/WWW/m4lib/whatis.m4 delete mode 100644 doc/examples/capitalize.m4 delete mode 100644 doc/examples/capitalize2.m4 delete mode 100644 doc/examples/comments.m4 delete mode 100644 doc/examples/curry.m4 delete mode 100644 doc/examples/ddivert.m4 delete mode 100644 doc/examples/debug.m4 delete mode 100644 doc/examples/esyscmd.m4 delete mode 100644 doc/examples/exp.m4 delete mode 100644 doc/examples/foreach.m4 delete mode 100644 doc/examples/foreach2.m4 delete mode 100644 doc/examples/foreachq.m4 delete mode 100644 doc/examples/foreachq2.m4 delete mode 100644 doc/examples/foreachq3.m4 delete mode 100644 doc/examples/foreachq4.m4 delete mode 100644 doc/examples/forloop.m4 delete mode 100644 doc/examples/forloop2.m4 delete mode 100644 doc/examples/forloop3.m4 delete mode 100644 doc/examples/fstab.m4 delete mode 100644 doc/examples/hanoi.m4 delete mode 100644 doc/examples/incl-test.m4 delete mode 100644 doc/examples/incl.m4 delete mode 100644 doc/examples/include.m4 delete mode 100644 doc/examples/indir.m4 delete mode 100644 doc/examples/join.m4 delete mode 100644 doc/examples/loop.m4 delete mode 100644 doc/examples/misc.m4 delete mode 100644 doc/examples/modtest.m4 delete mode 100644 doc/examples/multiquotes.m4 delete mode 100644 doc/examples/patsubst.m4 delete mode 100644 doc/examples/pushpop.m4 delete mode 100644 doc/examples/quote.m4 delete mode 100644 doc/examples/regexp.m4 delete mode 100644 doc/examples/reverse.m4 delete mode 100644 doc/examples/shadow.m4 delete mode 100644 doc/examples/stack.m4 delete mode 100644 doc/examples/stack_sep.m4 delete mode 100644 doc/examples/stdlib.m4 delete mode 100644 doc/examples/sysv-args.m4 delete mode 100644 doc/examples/time.m4 delete mode 100644 doc/examples/time2.m4 delete mode 100644 doc/examples/trace.m4 delete mode 100644 doc/examples/translit.m4 delete mode 100644 doc/examples/undivert.incl delete mode 100644 doc/examples/undivert.m4 delete mode 100644 doc/examples/wrap.m4 delete mode 100644 doc/examples/wrapfifo.m4 delete mode 100644 doc/examples/wraplifo.m4 delete mode 100644 doc/examples/wraplifo2.m4 delete mode 100644 doc/m4.texi delete mode 100644 m4/builtin.c delete mode 100644 m4/debug.c delete mode 100644 m4/hash.c delete mode 100644 m4/hash.h delete mode 100644 m4/input.c delete mode 100644 m4/m4.c delete mode 100644 m4/m4module.h delete mode 100644 m4/m4private.h delete mode 100644 m4/macro.c delete mode 100644 m4/module.c delete mode 100644 m4/output.c delete mode 100644 m4/path.c delete mode 100644 m4/resyntax.c delete mode 100644 m4/symtab.c delete mode 100644 m4/syntax.c delete mode 100644 m4/system_.h delete mode 100644 m4/utility.c delete mode 100644 modules/evalparse.c delete mode 100644 modules/format.c delete mode 100644 modules/gnu.c delete mode 100644 modules/m4.c delete mode 100644 modules/m4.h delete mode 100644 modules/mpeval.c delete mode 100644 modules/stdlib.c delete mode 100644 modules/time.c delete mode 100644 modules/traditional.c delete mode 100644 po/Makevars delete mode 100644 po/POTFILES.in delete mode 100644 src/freeze.c delete mode 100644 src/m4.h delete mode 100644 src/main.c delete mode 100644 src/stackovf.c delete mode 100644 tests/atlocal.in delete mode 100644 tests/builtins.at delete mode 100644 tests/freeze.at delete mode 100755 tests/generate.awk delete mode 100644 tests/import.c delete mode 100644 tests/iso8859.m4 delete mode 100644 tests/m4.in delete mode 100644 tests/macros.at delete mode 100644 tests/modtest.c delete mode 100644 tests/modules.at delete mode 100644 tests/null.err delete mode 100644 tests/null.m4 delete mode 100644 tests/null.out delete mode 100644 tests/options.at delete mode 100644 tests/others.at delete mode 100644 tests/shadow.c delete mode 100755 tests/stackovf.test delete mode 100644 tests/testsuite.at diff --git a/.autom4te.cfg b/.autom4te.cfg deleted file mode 100644 index f47eaeee..00000000 --- a/.autom4te.cfg +++ /dev/null @@ -1,4 +0,0 @@ -# Disable the autom4te.cache directory. -begin-language: "Autoconf-without-aclocal-m4" -args: --no-cache -end-language: "Autoconf-without-aclocal-m4" diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index f7c0ed7c..00000000 --- a/.gitattributes +++ /dev/null @@ -1,5 +0,0 @@ -# See ./bootstrap for some helpful ~/.gitconfig or .git/config settings -# needed for using these attributes effectively. -*.texi* diff=texinfo -null.* diff merge -iso8859.m4 diff merge diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e0841d1e..00000000 --- a/.gitignore +++ /dev/null @@ -1,91 +0,0 @@ -*~ -.#* -*.a -*.bak -.deps -.dirstamp -*.exe -*.gmo -*.header -*.la -.libs -*.lo -*.log -*.mo -*.o -*.orig -*.patch -.patch_number -*.po -*.pot -*.rej -*.sin -/.tarball-version -/.version -ABOUT-NLS -/aclocal.m4 -/aclocal.m4t -autom4te.cache -build-aux/ -!build-aux/gl/ -!build-aux/gnulib/ -!build-aux/m4/ -!build-aux/thanks-gen -/ChangeLog -/config.cache -/config.h -/config.h.in -/config.log -/config.status -/configure -cscope.* -CVS -/doc/.gitignore -/doc/m4.1 -/doc/m4.?? -/doc/m4.??? -/doc/m4.html -/doc/m4.info* -/doc/manual -/doc/stamp-vti -/doc/version.texi -/GNUmakefile -/INSTALL -libtool -/m4-* -/m4/gnu -/m4/obstack.h -/m4/pathconf.h -/m4/system.h -/maint.mk -Makefile -Makefile.in -Makefile.inc -/patches -/po/.reference -/po/*.sed -/po/LINGUAS -/po/Makefile.in.in -/po/Makevars.template -/po/POTFILES -/po/Rules-quot -/po/stamp-po -/src/assure* -/src/getopt* -/src/m4 -/src/version-etc* -/src/xstrto* -/stamp-h -/stamp-h1 -/stamp-h.in -/stamp-vcl -/tests/at-* -/tests/atconfig -/tests/atlocal -/tests/m4 -/tests/generated.at -/tests/gnu -/tests/package.m4 -/tests/testsuite -/tests/testsuite.dir -/tests/testsuite.log diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 0d4d08ae..00000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "gnulib"] - path = build-aux/gnulib - url = git://git.sv.gnu.org/gnulib.git diff --git a/.prev-version b/.prev-version deleted file mode 100644 index f689e8c1..00000000 --- a/.prev-version +++ /dev/null @@ -1 +0,0 @@ -1.4.18 diff --git a/.x-update-copyright b/.x-update-copyright deleted file mode 100644 index d0a3998e..00000000 --- a/.x-update-copyright +++ /dev/null @@ -1 +0,0 @@ -ltdl/m4/gnulib-cache.m4 diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 73ce2f95..00000000 --- a/AUTHORS +++ /dev/null @@ -1,43 +0,0 @@ -Authors of GNU M4. - -The following contributors have warranted legal paper exchanges with -the Free Software Foundation for their contributions to GNU M4. Also -see the files ChangeLog and THANKS. This list results from searching -for /\bM4\b/ in the file /gd/gnuorg/copyright.list on the -fencepost.gnu.org machine. - -Rene' Seindal seindal@diku.dk 1990-03-28 -James L. Avera jima@netcom.com 1993-10-04 -Pete Chown pete.chown@dale.dircon.co.uk 1994-06-28 -John Gerard Makecki johnm@vlibs.com 1995-04-24 -Francois Pinard pinard@iro.umontreal.ca 1996-02-01 -Thomas Tanner tanner@ffii.org 1999-06-23 -Gary V. Vaughan gary@gnu.org 2000-10-02 -Yuji Minejima ? 2001-05-09 -Akim Demaille akim@freefriends.org 2001-11-01 -Andrew James Bettison andrewb@zip.com.au 2001-11-19 -Noah Jeffrey Misch noah@cs.caltech.edu 2004-07-05 -Michael Elizabeth Chastain mec@shout.net 2001-12-27 -William C. Cox bill@qswtools.com 2004-12-04 -Alexandre Duret-Lutz adl@gnu.org 2004-12-04 -John Gatewood Ham zappaman@buraphalinux.org 2005-11-01 -Eric Benjamin Blake ebb9@byu.net 2006-01-18 -John Brzustowski jbrzusto@fastmail.fm 2006-03-06 -Ralf Wildenhues Ralf.Wildenhues@gmx.de 2006-03-20 -Markus Duft markus.duft@salomon.at 2006-08-03 -Joel E. Denny jdenny@clemson.edu 2009-08-18 -David Warme David.Warme@Group-W-Inc.com 2010-03-10 -Raphael Poss m4-patches@raphael.poss.name 2010-10-04 -Tim Rice tim@multitalents.net 2011-01-24 - -======================================================================== - -Copyright (C) 2000, 2006-2007, 2010, 2013-2014, 2017 Free Software -Foundation, Inc. - -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.3 or -any later version published by the Free Software Foundation; with no -Invariant Sections, with no Front-Cover Texts, and with no Back-Cover -Texts. A copy of the license is included in the ``GNU Free -Documentation License'' file as part of this distribution. diff --git a/COPYING b/COPYING deleted file mode 100644 index a9e5a4cc..00000000 --- a/COPYING +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007, 2013-2014, 2017 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/ChangeLog.old b/ChangeLog.old deleted file mode 100644 index ab146a8e..00000000 --- a/ChangeLog.old +++ /dev/null @@ -1,12324 +0,0 @@ -2010-03-02 Giuseppe Scrivano (tiny change) - - Support bootstrap --gnulib-srcdir=DIR. - * bootstrap: Add --gnulib-srcdir option, which overrides - GNULIB_SRCDIR, for consistency with gnulib bootstrap. - -2010-03-01 Eric Blake - - Mention release of version 1.4.14. - * gnulib: Update to latest. - * README: Drop CVS mention. - * HACKING: Tweak release instructions. - * NEWS: Mention the release. - * .prev-version: Record previous version. - * cfg.mk (old_NEWS_hash): Auto-update. - -2010-02-24 Eric Blake - - Improve parsing example. - * doc/m4.texinfo (Input processing): Double-quote argument to - translit, for robustness. - * THANKS: Update. - Reported by Chris Penev. - -2010-01-29 Eric Blake - - Document upcoming release. - * gnulib: Update to latest. - * doc/m4.texinfo (History): Mention 1.4.14. - * Makefile.am (src/getopt.h): Drop dependence on now-obsolete - link-warning.h. - -2010-01-08 Eric Blake - - Address remaining 'make syntax-check' findings. - * gnulib: Update to latest. - * Makefile.am (tests/package.m4): Avoid @@ substitution. - (src_m4_LDADD): Link with libiconv. - * m4/m4private.h (STREQ): New macro. - * m4/resyntax.c (m4_regexp_syntax_encode): Use it. - * src/main.c (process_file): Likewise. - (includes): Drop unused header. - * m4/macro.c (m4_arg_equal): Adjust comment. - * m4/syntax.c: Likewise. - * m4/system_.h: Avoid useless preprocessor parenthesis. - * ltdl/m4/stackovf.m4 (M4_SYS_STACKOVF): Likewise. - * src/stackovf.c: Likewise. - (setup_stackovf_trap): Mark diagnostics. - * modules/mpeval.c (includes): Move quotearg.h inclusion... - * modules/evalparse.c (includes): ...to where it is used. - * cfg.mk (local-checks-to-skip): Exempt tests that cause spurious - failures, but first fix what they were intended to detect. - (_makefile_at_at_check_exceptions): Allow an exception. - -2010-01-07 Eric Blake - - Use correct license on auxiliary documentation. - * gnulib: Update to latest. - * AUTHORS: Use GFDL 1.3, not 1.2. - * README-alpha: Likewise. - * README: Likewise. - * THANKS: Likewise. - * doc/STYLE: Likewise. - * modules/README: Likewise. - * NEWS: Place under GFDL. - * TODO: Likewise. - * cfg.mk (old_NEWS_hash): Update. - - Address 'make sc_error_message_uppercase' failures. - * m4/output.c (m4_freeze_diversions): Silence false positive. - * src/main.c (main): Use 'warning', not 'Warning', in messages. - * m4/utility.c (m4_verror_at_line): Likewise. - * doc/m4.texinfo (Operation modes, Macro Arguments, Undefine) - (Defn, Pushdef, Indir, Builtin, Ifdef, Ifelse, Dumpdef, Trace) - (Debuglen, Debugfile, Dnl, Changeresyntax, Standard Modules) - (Index macro, Regexp, Substr, Translit, Patsubst, Format, Incr) - (Eval, Mkstemp, Syncoutput, Improved forloop) - (Improved fatal_error): Adjust expected output. - * tests/builtins.at (define, mkdtemp, mkstemp): Likewise. - * tests/freeze.at (loading format 1, reloading unknown builtin): - Likewise. - * tests/macros.at (Arity and defn, 'Arity, defn, and freeze') - (pushdef/popdef): Likewise. - * tests/null.err: Likewise. - * tests/options.at (deprecated options, POSIXLY_CORRECT) - (--fatal-warnings, --regexp-syntax, --syncoutput): Likewise. - * tests/others.at (nul character, stdin seekable): Likewise. - * tests/modules.at (AT_CHECK_M4_MODTEST, modules: text): - Likewise. - - Address 'make sc_cast_of_argument_to_free' failures. - * m4/m4private.h (DELETE): Adjust comment and fix parentheses. - * m4/m4.c (m4_delete): Use it to avoid warning. - * m4/module.c (install_builtin_table, module_remove): Likewise. - * m4/symtab.c (m4_symbol_value_delete, m4_symbol_value_copy): - Likewise. - * .x-sc_cast_of_argument_to_free: New file. - * Makefile.am (syntax_check_exceptions): Distribute exceptions. - - More whitespace cleanup. - * HACKING: Nuke trailing whitespace. - * examples/WWW/Makefile: Likewise. - * examples/WWW/_footer.htm: Likewise. - * examples/WWW/_header.htm: Likewise. - * examples/WWW/m4lib/bugs.m4: Likewise. - * examples/WWW/m4lib/html.m4: Likewise. - * examples/WWW/m4lib/menu.m4: Likewise. - * examples/WWW/m4lib/visions.m4: Likewise. - * examples/esyscmd.m4: Likewise. - * examples/fstab.m4: Avoid space-tab. - * examples/patsubst.m4: Likewise. - * NEWS: Prefer space over tab for alignment. - * THANKS: Likewise. - * TODO: Likewise. - * bootstrap: Likewise. - * configure.ac: Likewise. - * ltdl/m4/stackovf.m4: Likewise. - * m4/hash.c: Likewise. - * m4/hash.h: Likewise. - * m4/input.c: Likewise. - * m4/m4.c: Likewise. - * m4/m4module.h: Likewise. - * m4/m4private.h: Likewise. - * m4/macro.c: Likewise. - * m4/module.c: Likewise. - * m4/output.c: Likewise. - * m4/path.c: Likewise. - * m4/resyntax.c: Likewise. - * m4/symtab.c: Likewise. - * m4/syntax.c: Likewise. - * m4/system_.h: Likewise. - * modules/evalparse.c: Likewise. - * modules/format.c: Likewise. - * modules/gnu.c: Likewise. - * modules/import.c: Likewise. - * modules/load.c: Likewise. - * modules/m4.c: Likewise. - * modules/m4.h: Likewise. - * modules/modtest.c: Likewise. - * modules/mpeval.c: Likewise. - * modules/perl.c: Likewise. - * modules/shadow.c: Likewise. - * modules/stdlib.c: Likewise. - * modules/time.c: Likewise. - * modules/traditional.c: Likewise. - * src/freeze.c: Likewise. - * src/main.c: Likewise. - * src/stackovf.c: Likewise. - * tests/stackovf.test: Likewise. - * doc/STYLE: Mention the change. - -2010-01-05 Eric Blake - - Document new indentation policy. - * HACKING: Document indentation policy. - * .x-sc_prohibit_tab_based_indentation: New file. - * cfg.mk (sc_prohibit_tab_based_indentation): New rule. - * Makefile.am (syntax_check_exceptions): Ship exception. - - Switch to indentation by space, not tab. - * .gitmodules: Convert leading tabs to spaces. - * TODO: Likewise. - * bootstrap: Likewise. - * configure.ac: Likewise. - * examples/WWW/m4lib/html.m4: Likewise. - * examples/WWW/m4lib/layout.m4: Likewise. - * examples/WWW/m4lib/menu.m4: Likewise. - * ltdl/m4/debug.m4: Likewise. - * ltdl/m4/gmp.m4: Likewise. - * ltdl/m4/m4-obstack.m4: Likewise. - * ltdl/m4/stackovf.m4: Likewise. - * m4/builtin.c: Likewise. - * m4/debug.c: Likewise. - * m4/hash.c: Likewise. - * m4/hash.h: Likewise. - * m4/input.c: Likewise. - * m4/m4.c: Likewise. - * m4/m4module.h: Likewise. - * m4/m4private.h: Likewise. - * m4/macro.c: Likewise. - * m4/module.c: Likewise. - * m4/output.c: Likewise. - * m4/path.c: Likewise. - * m4/resyntax.c: Likewise. - * m4/symtab.c: Likewise. - * m4/syntax.c: Likewise. - * m4/utility.c: Likewise. - * modules/evalparse.c: Likewise. - * modules/format.c: Likewise. - * modules/gnu.c: Likewise. - * modules/load.c: Likewise. - * modules/m4.c: Likewise. - * modules/m4.h: Likewise. - * modules/mpeval.c: Likewise. - * modules/perl.c: Likewise. - * modules/stdlib.c: Likewise. - * modules/time.c: Likewise. - * src/freeze.c: Likewise. - * src/m4.h: Likewise. - * src/main.c: Likewise. - * src/stackovf.c: Likewise. - * tests/builtins.at: Likewise. - * tests/freeze.at: Likewise. - * tests/generate.awk: Likewise. - * tests/modules.at: Likewise. - * tests/others.at: Likewise. - * tests/stackovf.test: Likewise. - * tests/testsuite.at: Likewise. - - Update copyright year. - All files impacted, via 'make update-copyright'. Additionally: - * .gitignore: Ignore backup files. - - Prepare to bulk update copyright year. - * gnulib: Update. - * ltdl/m4/gnulib-cache.m4: Import update-copyright module. - * cfg.mk (update-copyright-env): Enforce longhand behavior. - * .x-update-copyright: New file. - * Makefile.am (syntax_check_exceptions): Distribute exception. - * ltdl/m4/debug.m4: Add FSF copyright. - * ltdl/m4/m4-error.m4: Fix FSF name in copyright. - * ltdl/m4/m4-getopt.m4: Likewise. - * ltdl/m4/m4-gettext.m4: Likewise. - * ltdl/m4/m4-obstack.m4: Likewise. - * ltdl/m4/m4-regex.m4: Likewise. - * ltdl/m4/m4-rename.m4: Likewise. - * ltdl/m4/m4-syscmd.m4: Likewise. - * modules/modtest.m4: Likewise. - * modules/perl.m4: Likewise. - * modules/shadow.m4: Likewise. - * modules/stdlib.m4: Likewise. - * modules/time.m4: Likewise. - * modules/time2.m4: Likewise. - * tests/iso8859.m4: Likewise. - - Use gnulib maintainer-makefile module. - * ltdl/m4/gnulib-cache.m4: Import maintainer-makefile module. - * cfg.mk (local-checks-to-skip): Drop changelog-check; add - sc_cast_of_x_alloc_return_value. - (gnu_ftp_host-alpha, gnu_ftp_host-beta, gnu_ftp_host-major) - (gnu_rel_host): Delete; provided by maint.mk. - (old_NEWS_hash): New macro. - * .prev-version: New file. - * .x-sc_require_config_h: Likewise. - * .x-sc_require_config_h_first: Likewise. - * Makefile.am (syntax_check_exceptions, EXTRA_DIST): Ship new - files. - * maint.mk: Remove from version control; use gnulib instead. - * .gitignore: Update. - - Update to latest gnulib. - * gnulib: Update. - * ltdl/m4/gnulib-cache.m4: Import xoset. - * m4/output.c (includes): Ensure that gnulib oset usage will - call xalloc_die on memory failure. - * Makefile.am (src/getopt.h): Update snippet from gnulib. - (LINK_WARNING_H, ARG_NONNULL_H): New macros. - - Fix testsuite failure on newer glibc. - * tests/testsuite.at (AT_CHECK_M4): Tolerate alternate getopt - spellings. - * tests/options.at (deprecated options, unknown option) - (--debugmode): Adjust expected output accordingly. - Reported by Ralf Wildenhues. - -2009-11-26 Eric Blake - - Update to newer gnulib. - * gnulib: Update. - * ltdl/m4/gnulib-cache.m4: Import inttypes, setenv, and unsetenv - modules. - * modules/m4.c (m4_make_temp): Adjust gen_tempname client. - * bootstrap (src_modules): Pick up getopt-gnu and its - dependencies. - * configure.ac (gl_VERSION_ETC): Support ./configure - --with-packager. - (AC_CHECK_FUNCS_ONCE): Rely on gnulib for setenv, unsetenv. - * ltdl/m4/m4-getopt.m4: Rewrite to match current gnulib. - * Makefile.am (src/getopt.h): Likewise. - * modules/stdlib.c (setenv, unsetenv): Rely on gnulib. - -2009-08-24 Eric Blake - - Pick up gnulib fixes for sub-process execution. - * gnulib: Update. - * tests/others.at (stdin and stdout closed): New test, to avoid - regression introduced on 1.4 branch on 2008-07-17. - * NEWS: Document the change. - - A status of 127 does not always imply esyscmd failure. - * modules/gnu.c (esyscmd): Silence gnulib message; regression - introduced 2009-03-13. - * doc/m4.texinfo (Sysval): Test this. - * NEWS: Document the change. - -2009-06-26 Eric Blake - - Use bitrotate for hashing. - * gnulib: Update to latest. - * ltdl/m4/gnulib-cache.m4: Import bitrotate module. - * m4/hash.c (m4_hash_string_hash): Use it. - - Fix description of limits on diversions. - * doc/m4.texinfo (Diversions): Fix grammar. Be less pessimistic - about limitations. - * THANKS: Update. - Reported by Elias Benali. - -2009-06-17 Eric Blake - - Stress test for hash resizing. - * tests/builtins.at (define): Enhance test. - -2009-06-15 Eric Blake - - Document why bootstrap might touch state of tree. - * bootstrap: Fix typos. Add comment. - * HACKING: Add notes about this scenario. - * gnulib: Update to latest version. - * .gitignore: Track gnulib changes. - - Drop .cvsignore and redundant .gitignore files. - * .cvsignore: Delete. We are moving further away from CVS. - * build-aux/.cvsignore: Likewise. - * doc/.cvsignore: Likewise. - * examples/.cvsignore: Likewise. - * ltdl/.cvsignore: Likewise. - * m4/.cvsignore: Likewise. - * modules/.cvsignore: Likewise. - * po/.cvsignore: Likewise. - * src/.cvsignore: Likewise. - * tests/.cvsignore: Likewise. - * .gitignore: Consolidate from other files. - * build-aux/.gitignore: Delete, now that it is consolidated. - * doc/.gitignore: Likewise. - * examples/.gitignore: Likewise. - * ltdl/.gitignore: Likewise. - * m4/.gitignore: Likewise. - * modules/.gitignore: Likewise. - * po/.gitignore: Likewise. - * src/.gitignore: Likewise. - * tests/.gitignore: Likewise. - * bootstrap: Simplify accordingly. Sync gnulib tree prior to - libtoolize, to avoid libtool overwriting config.guess. - - Avoid compiler warning. - * m4/macro.c (process_macro): Use correct type for isdigit. - -2009-06-13 Eric Blake - - Avoid snprintf link failures. - * ltdl/m4/gnulib-cache.m4: Import snprintf-posix module. - Reported by Ralf Wildenhues. - -2009-06-12 Ralf Wildenhues - - Avoid pointer arithmetic on `void *'. - * modules/m4.c (dump_symbol_CB): Cast obstack_base return value - to `char *' before using it. - -2009-05-04 Eric Blake - - Silence verbose testsuite runs. - * tests/testsuite.at (m4_version_prereq): Bump to recent - autoconf.git version where stdout-nolog was added. - * tests/builtins.at (esyscmd, syscmd): Use new stdout-nolog. - * tests/freeze.at (AT_TEST_FREEZE): Likewise. - * tests/others.at (stderr closed): Likewise. - * HACKING: Mention new requirement. - * bootstrap: Likewise. - Reported by Ralf Wildenhues. - -2009-04-21 Eric Blake - - Be more explicit about default quoting characters. - * doc/m4.texinfo (Quoted strings): Call out characters by name. - * THANKS: Update. - Suggested by Mehul Sanghvi. - -2009-04-16 Eric Blake - - Use gnulib rename module. - * ltdl/m4/gnulib-cache.m4: Import rename module. At the moment, - we don't tickle either of the platform bugs that it fixes, but it - is better to be safe than sorry. - - Require newer automake features. - * configure.ac (AM_INIT_AUTOMAKE): Add dist-xz, color-tests, - parallel-tests, and silent-rules. Drop dist-lzma. - * HACKING: Update minimum requirements. - * gnulib: Update to latest version. - - Mention release of 1.4.13. - * NEWS: Update to match release on branch-1.4. - * doc/m4.texinfo (History): Update release history. - (copying): Finish conversion to GFDL 1.3, started 2008-11-04. - -2009-03-23 Eric Blake - - Exploit git submodule by adding appropriate symlinks. - * bootstrap: No longer copy files from gnulib. - * COPYING: Change to symlink pointing into gnulib. - * INSTALL: Likewise. - * build-aux/compile: Likewise. - * build-aux/config.guess: Likewise. - * build-aux/config.sub: Likewise. - * build-aux/depcomp: Likewise. - * build-aux/install-sh: Likewise. - * build-aux/mdate-sh: Likewise. - * build-aux/missing: Likewise. - * build-aux/texinfo.tex: Likewise. - * .cvsignore: Reflect these changes. - * .gitignore: Likewise. - * build-aux/.cvsignore: New file. - * build-aux/.gitignore: Likewise. - - Make gnulib a git submodule. - * .gitmodules: New file. - * gnulib: Record which version of gnulib has been tested. - * bootstrap: Aid in submodule usage. - * cfg.mk (gnulib_dir): Alter default location of gnulib. - * HACKING: Mention how to use submodule. - -2009-03-21 Eric Blake - - Use memcmp2 to simplify lexicographic comparisons. - * ltdl/m4/gnulib-cache.m4: Import memcmp2. - * modules/m4.c (dumpdef_cmp_CB): Use it. - -2009-03-19 Ralf Wildenhues - - Fix m4.1 build race, exposed by parallelism through GNUmakefile. - * Makefile.am (SUBDIRS): Add doc. - (Documentation rules): Move ... - * doc/Makefile.am: ... to this new file. - * configure.ac (AC_CONFIG_FILES): Generate doc/Makefile. - -2009-03-13 Eric Blake - - Try to tolerate spaces in directory names in testsuite. - * tests/null.m4: Provide shell quoting, in case __program__ - contains spaces. - - Fix awk script portability. - * checks/get-them: In gsub, properly escape {. - Reported by Gary V. Vaughan. - - Make bootstrap easier on Solaris. - * bootstrap: Add GNULIB_SRCDIR. Useful when a wrapper script - gnulib-tool exists earlier on the path to work around /bin/sh - failure in parsing $GNULIB_SRCDIR/gnulib-tool. - -2009-03-13 Eric Blake - - Allow configuration choice in syscmd shell. - * ltdl/m4/m4-syscmd.m4: New file. - * configure.ac (M4_SYSCMD): Use it to provide - --with-syscmd-shell. - (AC_CHECK_HEADERS_ONCE): No longer need to worry about - . - * modules/m4.c (syscmd): Use it to avoid hard-coding the shell - location. - * modules/gnu.c (esyscmd): Likewise. - * doc/m4.texinfo (Syscmd, Esyscmd): Document this. - * README: Document new configure option. - * NEWS: Likewise. - - Use gnulib pipe module instead of popen(3). - * ltdl/m4/gnulib-cache.m4: Import pipe and wait-process modules. - * modules/gnu.c (M4_SYSVAL_EXITBITS, M4_SYSVAL_TERMSIGBITS): - Delete. - (esyscmd): Rewrite with pipe module. - Resolves a failure on AIX, reported by Gary V. Vaughan. - - Use gnulib execute module instead of system(3). - * ltdl/m4/gnulib-cache.m4: Import execute module. - * m4/utility.c (m4_info_name): New function. - * m4/m4module.h (m4_info_name): New prototype. - * modules/m4.c (syscmd): Rewrite with execute module. - (M4_SYSVAL_EXITBITS, M4_SYSVAL_TERMSIGBITS, m4_sysval): Move - computation... - * modules/gnu.c (M4_SYSVAL_EXITBITS, M4_SYSVAL_TERMSIGBITS) - (esyscmd): ...here. - Resolves a failure on AIX, reported by Gary V. Vaughan. - -2009-03-05 Eric Blake - - Improve web-manual maintainer rule. - * maint.mk (web-manual): Factor package-specific detail... - * cfg.mk (manual_title): ...to new variable. - -2009-02-23 Eric Blake - - Speed up translit when from argument is short. - * modules/m4.c (translit): Use memchr2 when possible. - * tests/builtins.at (translit): Add tests. - * NEWS: Document this. - -2009-02-18 Eric Blake - - Prefer buffer over byte operations. - * modules/format.c (format): Use memchr for speed. - * modules/gnu.c (substitute): Likewise. - * m4/macro.c (locate_dollar): Inline into only caller... - (process_macro): ...and rearrange for readability. - * m4/input.c (consume_buffer): Allow C++ compilation. - * doc/m4.texinfo (Changesyntax): Enhance test. - - Speed up esyscmd with buffer reads. - * modules/gnu.c (esyscmd): Read blocks directly into obstack, - rather than repeatedly reading bytes. Detect read errors. - - Avoid risk of stack overflow. - * m4/output.c (insert_file): Avoid stack allocation of large - buffer. - - Synchronize THANKS with branch. - * THANKS: Import more names. - - Improve handling of $ in syntax table. - * m4/m4module.h (m4_is_syntax_single_dollar): New function. - (M4_SYNTAX_DOLLAR, M4_SYNTAX_LBRACE, M4_SYNTAX_RBRACE): Change to - be context rather than basic syntax categories. - (M4_SYNTAX_MASKS): Adjust macro. - * m4/m4private.h (struct m4_syntax_table): Add dollar and - is_single_dollar members. - (m4_is_syntax_single_dollar): Add fast alternative. - * m4/syntax.c (m4_syntax_create, reset_syntax_set): Adjust to - account for change to context categories. - (m4_set_syntax): Manage is_single_dollar. - (m4_is_syntax_single_dollar): New function. - * m4/macro.c (locate_dollar): New helper function. - (process_macro): Use it to speed up macro expansion. - * m4/input.c (m4__next_token): Adjust client. - * doc/m4.texinfo (Changesyntax): Document this. - -2009-02-17 Eric Blake - - Sync changecom documentation with branch. - * doc/m4.texinfo (Changecom): Tweak wording. - * NEWS: Import changes from the branch. - - Stage 29b: Process quotes and comments by buffer, not bytes. - Search for quote and comment delimiters by buffer when possible. - Memory impact: none. - Speed impact: noticeable improvement, from fewer function calls. - * ltdl/m4/gnulib-cache.m4: Import memchr2 module. - * m4/input.c (m4__next_token): Add buffer reads to quote and - comment parsing. - * NEWS: Document this. - -2009-02-16 Eric Blake - - Stage 29a: Process dnl and macro names by buffer, not bytes. - Enhance input engine to provide lookahead buffer, rather than - forcing clients to call next_char for every byte. Utilize this - for the simplest clients. - Memory impact: none. - Speed impact: noticeable improvement, from fewer function calls. - * ltdl/m4/gnulib-cache.m4: Import freadptr and freadseek modules. - * m4/input.c (struct input_funcs): Add virtual functions - buffer_func and consume_func. - (file_buffer, file_consume, string_buffer, string_consume) - (composite_buffer, composite_consume, eof_buffer): Implement - them. - (file_funcs, string_funcs, composite_funcs, eof_funcs): Update - vtables accordingly. - (buffer_retry): New sentinel. - (next_buffer, consume_buffer): New functions. - (m4_skip_line, match_input, consume_syntax): Use them for faster - parsing. - Suggested by Bruno Haible. - - Unify single and multi-character delimiter handling. - * m4/input.c (MATCH): Add a parameter. - (m4__next_token): Simplify logic and reduce redundancy. - (m4__next_token_is_open): Adjust caller. - * m4/syntax.c (m4_set_comment, m4_set_quotes): Handle delimiters - of differing lengths. - (m4_set_syntax): Recognize restoration of single delimiters. - - Revamp changesyntax vs. changequote interactions. - * m4/m4module.h (M4_SYNTAX_VALUE): Delete unused macro. - (M4_SYNTAX_SUSPECT): New macro. - * m4/m4private.h (struct m4_syntax_table): Add suspect field. - * m4/syntax.c (check_is_single_quotes, check_is_single_comments) - (check_is_macro_escaped): Delete, by inlining body... - (m4_set_syntax): ...into here. Improves handling between - changesyntax and changequote/changecom. - (add_syntax_set, subtract_syntax_set, set_syntax_set): Simplify, - and let suspect field track needed cleanup. - (m4_set_quotes, m4_set_comment): Adjust meaning of - is_single_quotes and is_single_comment flags to always be true if - only one delimiter exists, regardless of its length. Ensure that - the syntax categories M4_SYNTAX_LQUOTE and M4_SYNTAX_BCOMM are - only used on 1-byte delimiters. - (add_syntax_attribute, remove_syntax_attribute): Change signature - to allow the use of fewer casts. Adjust the suspect field when - necessary. - (m4_reset_syntax, set_quote_age): Adjust callers. - * m4/input.c (m4__next_token, m4__next_token_is_open): Simplify - callers. - * doc/m4.texinfo (Changesyntax): Update documentation and tests. - - Improve changesyntax documentation. - * doc/m4.texinfo (Changesyntax): Merge two tables into one - multitable. - - Fix regression in multicharacter quotes, from 2008-01-26. - * m4/input.c (m4__next_token): Fix typo. - * tests/builtins.at (changequote): Enhance test. - -2009-02-13 Eric Blake - - Speed up parsing when detecting input file change. - * m4/input.c (next_char): Clear input_change flag. Bug introduced - 2006-10-25. - -2009-02-12 Eric Blake - - Avoid quadratic code when walking definition stack. - * examples/stack_sep.m4: Use linear, not quadratic - implementation. - * doc/m4.texinfo (Improved copy): Fix documentation, based on - recent autoconf bug fix. - * tests/others.at (recursion): Enhance test. - -2009-02-11 Eric Blake - - Stage 28c: Warn on embedded NUL in remaining cases. - Ensure all remaining warnings can handle embedded NUL. - Memory impact: none. - Speed impact: none noticed. - * m4/m4module.h (m4_debug_decode, m4_parse_truth_arg): Add - parameter. - * m4/macro.c (m4_macro_call): Improve diagnostic. - * modules/m4.c (defn): Likewise. - * m4/debug.c (m4_debug_decode): Handle embedded NUL. - * m4/utility.c (m4_parse_truth_arg): Likewise. - * modules/format.c (arg_int, arg_long, arg_double): Likewise. - (arg_string): New function. - (ARG_INT, ARG_LONG, ARG_STR, ARG_DOUBLE): Update callers. - * src/main.c (main): Likewise. - * src/freeze.c (reload_frozen_state): Likewise. - * modules/gnu.c (debugmode, syncoutput): Likewise. - * tests/options.at (--regexp-syntax): Adjust test. - * tests/freeze.at (reloading nul): Likewise. - * tests/null.m4: Likewise. - * tests/null.out: Likewise. - * tests/null.err: Likewise. - - Stage 28b: Warn on embedded NUL in file arguments. - Quote warning messages related to file and other NUL-terminated - system commands. - Memory impact: none. - Speed impact: none noticed. - * m4/path.c (m4_path_search): Quote file names in message. - * modules/m4.c (syscmd, include, m4_make_temp): Handle embedded - NUL. - * modules/gnu.c (debugfile, esyscmd): Likewise. - * tests/others.at (nul character): Adjust test. - * tests/builtins.at (mkdtemp, mkstemp): Likewise. - * tests/null.m4: Likewise. - * tests/null.out: Likewise. - * tests/null.err: Likewise. - - Stage 28a: Warn on embedded NUL in numeric arguments. - Quote warning messages related to numeric parsing in order to - handle embedded NUL. - Memory impact: none. - Speed impact: none noticed. - * m4/m4module.h (m4_numeric_arg): Adjust prototype. - * m4/utility.c (m4_numeric_arg): Add parameter. - * modules/gnu.c (debuglen): Adjust callers. - * modules/m4.c (incr, decr, divert, undivert, m4exit, substr) - (index): Likewise. - * modules/evalparse.c (m4_evaluate): Likewise. - * modules/stdlib.c (setenv, getpwuid, srand): Likewise. - * modules/time.c (ctime, gmtime, localtime, mktime, strftime): - Likewise. - * doc/m4.texinfo (Changesyntax): Fix typo. - * tests/others.at (nul character): Adjust test. - * tests/null.m4: Likewise. - * tests/null.out: Likewise. - * tests/null.err: Likewise. - -2009-02-11 Eric Blake - - Avoid regression in popdef(undef). - * doc/m4.texinfo (Trace): Enhance test, to cover regression - recently fixed on the branch. - -2009-02-09 Eric Blake - - Enhance index to support starting offset. - * modules/m4.c (index): Add optional third argument. - * NEWS: Document this. - * doc/m4.texinfo (Index macro): Likewise. - (Macro Arguments): Adjust tests. - -2009-01-24 Eric Blake - - Add URLs to --help output. - * src/main.c (usage): Use enhanced version-etc features. - -2009-01-07 Eric Blake - - Enhance substr to support replacement text. - * doc/m4.texinfo (Substr): Document new semantics. - * modules/m4.c (substr): Support optional fourth argument. - * NEWS: Document this. - - Enhance substr to support negative values. - * doc/m4.texinfo (Substr): Document new semantics, and how to - simulate old. - * modules/m4.c (substr): Support negative values. - * NEWS: Document this. - -2009-01-05 Eric Blake - - Maintainer cleanups. - * HACKING: Remove mention of xdelta. - * Makefile.am (EXTRA_DIST, MAINTAINERCLEANFILES): Let gnulib take - care of distributing gendocs.sh. - * maint.mk (web-manual): Use new feature of gendocs. - * ltdl/m4/gnulib-cache.m4: Regenerate. - -2008-12-24 Eric Blake - - Relax eval as allowed by POSIX 2008. - * modules/evalparse.c (m4_evaluate): Warn, not error, on invalid - operator. Quote expression in warning. - * modules/mpeval.c (includes): Add quotearg.h. - * doc/m4.texinfo (Eval, Improved forloop): Update tests. - * NEWS: Update to reflect 1.6 support for `?:'. - -2008-12-23 Eric Blake - - Add debugmode(o) to control dumpdef output location. - * m4/m4module.h (M4_DEBUG_TRACE_OUTPUT_DUMPDEF): New enumerator. - (M4_DEBUG_TRACE_VERBOSE): Update. - * m4/debug.c (m4_debug_decode): Support new debug option. - * src/freeze.c (produce_debugmode_state): Likewise. - * modules/m4.c (dumpdef): When set, force dumpdef to stderr rather - than the debug file. - * src/main.c (usage): Document it. - * doc/m4.texinfo (Debugmode, Dumpdef, Debugging options) - (Debugfile): Likewise. - * NEWS: Likewise. - Based on an autoconf bug report by Paolo Bonzini. - - Make --debugfile argument optional. - * src/main.c (long_options): Make the argument optional, to allow - setting debug file back to stderr. - (main): Make --debugfile order-dependent. - (usage): Document this. - * doc/m4.texinfo (Debugging options): Likewise. - * NEWS: Likewise. - * tests/options.at (--debugfile): Enhance test. - (--safer): Adjust to new semantics. - -2008-12-22 Eric Blake - - Use @var correctly. - * doc/m4.texinfo (Operation modes, Preprocessor features) - (Limits control, Frozen state, Debugging options) - (Dynamic loading features): Use lower case names in @var. - (Improved copy): Use @code, not @var, as appropriate. - -2008-12-18 Eric Blake - - Deal with M4 1.4.x limitation on builtin tokens. - * doc/m4.texinfo (Composition): Mention limitation on curry. - (Improved copy): New node. - (Stacks): Fix typo. - * examples/stack.m4: Likewise. - * examples/stack_sep.m4: New file. - * Makefile.am (dist_pkgdata_DATA): Distribute it. - -2008-12-15 Eric Blake - - Double size of temp file cache. - * m4/output.c (tmp_file, tmp_file_owner): Split... - (tmp_file1, tmp_file2, tmp_file1_owner, tmp_file2_owner): ...into - two variables. - (tmp_file2_recent): New variable. - (m4_tmpopen, m4_tmpclose, m4_tmpremove, m4_tmprename) - (m4_output_exit): Adjust callers. - - Use fewer seeks on cached files. - * m4/output.c (m4_tmpfile): Use write, not append mode. - (m4_tmpopen): Add parameter to decide when to skip seeks. - (m4_tmprename, m4_make_diversion, insert_diversion_helper) - (m4_freeze_diversions): Adjust callers. - - Cache most recently spilled diversion. - * m4/output.c (tmp_file, tmp_file_owner): New variables, for - 1-deep cache of spilled diversions. - (m4_tmpfile): Open in append mode, since we might revisit - diversion without closing it now. - (m4_tmpopen): Check cache first. - (m4_tmpclose): Update cache, rather than closing. Add parameter. - (m4_tmpremove): Close cache before removing. - (m4_tmprename): Deal with open files when renaming. - (m4_output_exit): Close cache before exiting. - (make_room_for, m4_make_diversion, insert_diversion_helper): - Adjust callers. - * ltdl/m4/m4-rename.m4 (M4_RENAME): New file. - * configure.ac (M4_RENAME): Invoke it. - - Correctly track size of in-memory diversions. - * m4/output.c (insert_diversion_helper): Correctly track total - in-memory diversion size after undivert. - - Avoid quadratic behavior for some cases of divert/undivert. - * m4/output.c (struct m4_diversion): Improve comments. - (m4_tmpname, m4_make_diversion): Strengthen preconditions. - (m4_tmprename): New function. - (m4_output_init, m4_output_exit): Move after internal functions. - (make_room_for): Don't bother copying uninitialized bytes. - (insert_diversion_helper): Transfer metadata, rather than copying - contents, when undiverting into a previously unused diversion. - * tests/builtins.at (divert): Add a check to the test. - * doc/m4.texinfo (Undivert): Enhance test. - * NEWS: Document the speedup. - -2008-12-02 Eric Blake - - Stage 27: Allow embedded NUL in text processing macros. - Pass NUL through regular expressions, format, and translit, and - diagnose it in eval and changeresyntax. Improve warning - capabilities of format. - Memory impact: none. - Speed impact: none noticed. - * modules/m4.c (m4_expand_ranges): Don't append extra bytes. - (translit): Manage NUL bytes. - * modules/format.c (format): Likewise. - * modules/gnu.c (substitute, regexp_substitute): Likewise. - (m4_resyntax_encode_safe): Add parameter. - (regexp, patsubst, renamesyms): Update callers. - (regexp_compile): Adjust error message. - * modules/evalparse.c (m4_evaluate): Use consistent message. - (end_text): New variable. - (eval_init_lex): Add parameter. - (eval_lex): Detect embedded NUL. - * src/freeze.c (reload_frozen_state): Likewise. - * doc/m4.texinfo (Format): Update to cover new behavior. - (Eval): Mention that result is unquoted. - * tests/freeze.at (reloading nul): Enhance test. - * tests/null.m4: Likewise. - * tests/null.err: Update expected output. - * tests/null.out: Likewise. - * tests/options.at (--regexp-syntax): Likewise. - -2008-11-28 Eric Blake - - Resync NEWS with branches. - * NEWS: Mention 1.4.12, update state of 1.6. - -2008-11-26 Eric Blake - - Keep COPYING in repository. - * Makefile.am (MAINTAINERCLEANFILES): Don't remove COPYING. - * .cvsignore: Don't ignore it. - * .gitignore: Likewise. - * COPYING: Store in repository, per automake 1.10.2 - recommendation. - -2008-11-26 Eric Blake - - Document optimized forloop. - * doc/m4.texinfo (Improved forloop): Mention alternate style that - avoids define overhead. - * examples/forloop3.m4: New file. - * Makefile.am (dist_pkgdata_DATA): Distribute it. - - Document copy composite using stack_foreach and curry. - * doc/m4.texinfo (Stacks): New node, to document pushdef stack - manipulation. - (Ifelse): Move define_blind... - (Composition): ...to this new node. Document currying, then use - it to implement copy and rename. - * examples/curry.m4: New file. - * examples/stack.m4: Likewise. - * Makefile.am (dist_pkgdata_DATA): Distribute them. - -2008-11-04 Eric Blake - - Upgrade to FDL 1.3. - * ltdl/m4/gnulib-cache.m4: Replace fdl module with fdl-1.3. - * Makefile.am (doc_m4_TEXINFOS, MAINTAINERCLEANFILES): Reflect - file change. - * doc/m4.texinfo (GNU Free Documentation License): Likewise. - -2008-10-22 Eric Blake - - Give nicer error if user modifies testsuite but lacks autoconf. - * Makefile.am (AUTOM4TE): Use missing in the definition. - -2008-10-09 Eric Blake - - Allow user to choose which sed to use in testsuite. - * tests/atlocal.in (SED): Inherit from configure results. - * tests/builtins.at (__m4_@&t@version__, divert, esyscmd) - (mkstemp, syscmd): Use $SED. - * tests/generate.awk (new_test): Likewise. - * tests/options.at (deprecated options, unknown option) - (--debugmode, --help and --version): Likewise. - * tests/testsuite.at (AT_CHECK_M4): Likewise. - * tests/others.at (directory, stderr closed, stdin seekable) - (stdout closed): Likewise. - (nul character): Likewise. Also, skip test if sed can't handle - NUL bytes. - - Clean up testsuite invocation. - * tests/atlocal.in: Fix copyright notice. - * Makefile.am (TESTS_ENVIRONMENT): Delete; it wasn't being used. - (check-local, installcheck-local): Adjust clients. Add missing - dependency. - -2008-09-25 Eric Blake - - Tweak error message on command line failure. - * m4/m4private.h (includes): Use "quotearg.h". - * src/main.c (process_file, main): Use nicer quotes for file name - in error messages. - * m4/input.c (file_clean, m4_push_file): Likewise. - * m4/module.c (m4__module_open): Likewise. - * src/freeze.c (produce_frozen_state, reload_frozen_state): - Likewise. - * modules/gnu.c (debugfile): Likewise. - * modules/m4.c (undivert, include): Likewise. - * tests/others.at (directory, stdin closed): Update tests. - * tests/options.at (file names, --debugmode): Likewise. - * doc/m4.texinfo (Debugmode): Likewise. - - Unify error handling for reading directories. - * m4/path.c (m4_path_search): Factor open attempts... - (m4_fopen): ...into new function, to reject directories. - * tests/others.at (directory): Enhance test. - * doc/m4.texinfo (Include): Document that directories cannot be - input files. - - Avoid bugs on platforms that mishandle trailing /. - * ltdl/m4/gnulib-cache.m4: Import fopen module. - * tests/others.at (directory): New test. - -2008-09-16 Eric Blake - - Fix bootstrap for Solaris /bin/sh. - * bootstrap: Avoid shell quoting pitfall. - -2008-09-01 Ralf Wildenhues - - Typos in source code comments. - * modules/m4.c: Fix typos in comments. - * m4/input.c: Likewise. - * src/main.c: Likewise. - -2008-08-29 Eric Blake - - Fix manual date information. - * doc/m4.texinfo: UPDATED refers to the day the manual was built, - not the release date of M4. - Based on a bison patch by Akim Demaille. - -2008-08-27 Eric Blake - - Tweak -d examples. - * doc/m4.texinfo (Invoking m4): Fix example, since order of -d - matters. - (Dumpdef): Fix typo. - -2008-08-23 Eric Blake - - Allow debugmode control over whether defn(undef) warns. - * ltdl/m4/gnulib-cache.m4: Import verify module. - * m4/m4module.h (M4_DEBUG_TRACE_DEREF, M4_DEBUG_TRACE_INITIAL): - New values. - (M4_DEBUG_TRACE_VERBOSE, M4_DEBUG_TRACE_DEFAULT): Adjust. - * m4/m4.c (m4_create): Start with debugmode = d. - * src/main.c (usage): Mention this. - (main): Let -E impact debug mode. - * m4/utility.c (m4_symbol_value_lookup): Squelch undefined warning - if flag is clear. - * modules/gnu.c (builtin, inder): Likewise. - * m4/debug.c (m4_debug_decode): Parse new mode. - * src/freeze.c (produce_debugmode_state): Accomodate new mode. - * doc/m4.texinfo (Debugging options): Mention change in the - default behavior. - (Debugmode): Mention new flag d. - (Operation modes): Mention interaction with -E. - (Undefine, Defn, Pushdef, Indir, Builtin, Dumpdef): Document and - test its effect. - * tests/options.at (--debugmode): Update tests. - * tests/freeze.at (reloading debugmode): Likewise. - * NEWS: Document this. - Reported by Ralf Wildenhues; without this patch, M4 1.6+ would be - incompatible with Autoconf 2.62. - -2008-08-22 Eric Blake - - Improve --debugmode behavior. - * m4/m4module.h (m4_debug_decode): Simplify interface. - * m4/debug.c (m4_debug_decode): Remove parameter, and handle - setting the new value. - * modules/gnu.c (debugmode): Adjust caller. - * src/freeze.c (reload_frozen_state): Likewise. - * src/main.c (main): Likewise. - (usage): Fix default for --debug. - * doc/m4.texinfo (Debugging options): Add an example. - -2008-08-21 Eric Blake - - Avoid regression in defn(undef). - * doc/m4.texinfo (Trace): Enhance test, to cover regression - recently fixed on the branch. - -2008-08-18 Eric Blake - - Remove deprecated -N option; fixes a regression from 2006-09-14. - * src/main.c (DIVERSIONS_OPTION): Delete. - (long_options, OPTSTRING, main): Remove -N/--diversions option. - * doc/m4.texinfo (Limits control): Remove it from the manual. - * NEWS: Mention that it is gone. - * tests/options.at (deprecated options): Update test. - - Improve 'git diff' of manual source. - * .gitattributes (*.texi*): Add diff attribute. - * bootstrap: Tell git how to use it. - Inspired by Jim Meyering's similar patch for coreutils. - -2008-08-07 Bruno Haible (tiny change) - - Run m4 tests prior to gnulib unit tests. - * Makefile.am (SUBDIRS): Swap order of directories. - -2008-08-03 Eric Blake - - Stage 26: Allow embedded NUL in macro definitions. - Clean up final few locations that did not track macro definitions - by length, to allow embedded NUL. Make m4_arg_len callers aware - of issue of flattening builtins when determining length. - Memory impact: none. - Speed impact: none noticed. - * m4/m4module.h (m4_arg_len): Add parameter. - (M4ARGLEN): Provide default for the parameter. - * m4/m4private.h (includes): Share xmemdup0.h among all libm4 - files. - * m4/macro.c (m4_arg_len): Fail if builtins are not flattened. - * m4/syntax.c (includes): Rely on m4private.h for xmemdup0. - * m4/symtab.c (includes): Likewise. - (m4_symbol_value_copy): Use xmemdup0. - * m4/module.c (install_macro_table): Likewise. - * src/freeze.c (reload_frozen_state): Likewise. - * tests/freeze.at (reloading nul): Enhance test. - * tests/null.m4: Likewise. - * tests/null.err: Update expected output. - * tests/null.out: Likewise. - - Fix regression in commenting unbalanced quotes, from 2008-02-16. - * m4/m4private.h (m4__token_type): Add M4_TOKEN_COMMENT. - * m4/input.c (m4__next_token, m4_print_token): Supply new token - type for comments. - * m4/macro.c (expand_token): Penalize comments, as they can - contain unbalanced quotes; latent bug since 2007-12-07, exposed by - passing $@ references built from comments. - (expand_argument): Adjust caller. - * tests/others.at (Comments): Enhance test to catch it. - * NEWS: Mention the fix. - -2008-07-30 Eric Blake - - Fix regression in trace output, introduced 2008-05-08. - * m4/input.c (m4__push_symbol): When cloning chains, break pointer - back to original chain; latent bug from 2008-02-02 that did not - cause misbehavior until trace output read unfinished chain. - * tests/builtins.at (debug): Add test for this. - -2008-07-28 Eric Blake - - 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 - - Give example for O(n) foreach on m4 1.4.x. - * examples/foreachq4.m4: New file. - * Makefile.am (dist_pkgdata_DATA): Distribute it. - * tests/others.at (recursion): Test it. - * doc/m4.texinfo (Improved foreach): Document linear foreach with - m4 1.4.5 and greater. - -2008-07-19 Eric Blake - - Resynchronize docs from branch. - * doc/m4.texinfo (Undefine, Pushdef): Mention warning on undefined - name, particularly since the old documentation didn't match code. - (Standard Modules): Add caveat about using __m4_version__. - -2008-07-11 Eric Blake - - Bump required automake to 1.10a; regression introduced 2008-01-22. - * configure.ac (AM_INIT_AUTOMAKE): Undo requirement downgrade to - 1.10.1, since we also rely on pkglibexecdir. - * HACKING: Fix minimum requirement. - * bootstrap: Likewise. - * THANKS: Update. - Reported by Joel E. Denny. - - Avoid bogus whitespace in @ovar, @dvar. - * doc/m4.texinfo (ovar, dvar): Add @c. - Based on patch by Ralf Wildenhues to Autoconf manual. - -2008-06-23 Eric Blake - - Adjust to new gnulib-tool layout. - * ltdl/m4/gnulib-cache.m4: Reformat. - - Fix bootstrap comment. - * bootstrap: DOWNLOAD_PO was previously removed. - -2008-06-19 Eric Blake - - Revert speed regression from 2008-06-16. - * m4/output.c (m4_shipout_int): Avoid obstack_printf in hot path. - * modules/m4.c (numb_obstack): Likewise. - * m4/input.c (MATCH): Use fewer conditionals, and factor - adjustment of S... - (match_input): ...here for smaller code size. - * m4/syntax.c (m4_reset_syntax, m4_set_quotes, m4_set_comment): - Supply trailing NUL to delimiters, to meet contract of faster - MATCH. - -2008-06-18 Eric Blake - - Whitespace cleanup. - * m4/m4module.h: Use consistent spacing for pointer parameters. - * m4/m4private.h: Likewise. - - Stage 25b: Handle embedded NUL in changesyntax and friends. - Track quote and comment delimiters by length, to allow embedded - NUL. Improve changesyntax to support assigning syntax to NUL. - Memory impact: none. - Speed impact: none noticed. - * m4/m4module.h (m4_set_quotes, m4_set_comment, m4_set_syntax): - Add parameter. - (m4_reset_syntax): New prototype. - * m4/syntax.c (add_syntax_set, subtract_syntax_set) - (set_syntax_set, m4_set_quotes, m4_set_comment): Add parameter, to - handle embedded NUL. - (m4_set_syntax): Likewise. Also, split code to reset the table... - (m4_reset_syntax): ...into a new function. - (m4_syntax_create): Adjust callers. - * m4/input.c (match_input, MATCH): Add parameter. - (m4__next_token, m4__next_token_is_open): Adjust callers. - * modules/m4.h (m4_expand_ranges_func): Add parameter. - * modules/m4.c (dumpdef): Handle NUL in dumped quotes. - (changequote, changecom, translit, m4_expand_ranges): Track - delimiter length. - * modules/gnu.c (changesyntax): Handle embedded NUL. - * src/freeze.c (reload_frozen_state): Adjust callers. - * tests/freeze.at (reloading nul): Enhance test. - * tests/null.m4: Likewise. - * tests/null.out: Update expected output. - * tests/null.err: Likewise. - -2008-06-16 Eric Blake - - Stage 25a: Use obstack_printf for easier output. - Convert macro tracing and other locations to use obstack_printf - rather than hand-rolled equivalents. Ensure that embedded NUL in - trace output does not truncate the trace string. - Memory impact: none. - Speed impact: noticeable penalty, from obstack_printf overhead. - * ltdl/m4/gnulib-cache.m4: Import obstack-printf-posix module. - * m4/macro.c (trace_format): Delete; use obstack_printf instead. - (trace_header, trace_pre, trace_post): All callers updated. - * m4/output.c (m4_shipout_int, m4_tmpname): Use obstack_printf. - (m4_divert_text): Speed up syncline output. - * modules/m4.c (dumpdef): Handle embedded NUL. - (numb_obstack): Speed up eval output. - (maketemp): Use obstack_printf. - * modules/format.c (format): Likewise. - - Add missing const qualifications. - * m4/resyntax.c (m4_resyntax_map): Declare array elements as - const. - * modules/gnu.c (m4_builtin_table, m4_macro_table): Likewise. - * modules/import.c (m4_builtin_table): Likewise. - * modules/load.c (m4_builtin_table, m4_macro_table): Likewise. - * modules/m4.c (m4_builtin_table): Likewise. - * modules/modtest.c (m4_builtin_table, m4_macro_table): Likewise. - * modules/mpeval.c (m4_builtin_table, m4_macro_table): Likewise. - * modules/perl.c (m4_builtin_table, m4_macro_table): Likewise. - * modules/shadow.c (m4_builtin_table, m4_macro_table): Likewise. - * modules/stdlib.c (m4_builtin_table): Likewise. - * modules/time.c (m4_builtin_table): Likewise. - * modules/traditional.c (m4_macro_table): Likewise. - -2008-06-10 Eric Blake - - Avoid corrupted frozen file if NUL appears on block boundary. - * m4/output.c (insert_file): Separate consecutive quotearg blocks - with \, in case last byte of first block was NUL. - -2008-06-03 Eric Blake - - Fix printf type mismatches. - * m4/m4module.h (m4_bad_argc): Alter parameter type. - * m4/m4private.h (struct m4_call_info): Alter call_id type. - * m4/macro.c (expand_macro, m4__adjust_refcount): Use correct - specifiers. - * m4/utility.c (m4_bad_argc): Likewise. - - Borrow bootstrap ideas from gnulib. - * bootstrap (options, DOWNLOAD_PO): Remove --download-po; the - advertized subset of languages didn't work. Use --skip-po - instead, for consistency with gnulib bootstrap. - (func_get_translations): Use rsync, not wget. - (func_update_po): Use a reference directory, to avoid changing - timestamps on unchanged .po files. - * TODO: Update accordingly. - - Fix fallout from previous patch. - * doc/m4.texinfo (Builtin): Adjust expected output. - -2008-06-02 Eric Blake - - Stage 24c: Improve display of macro names with embedded NUL. - Quote instances of problematic characters in macro names when - presented to user. Track location via call_info rather than - munging context for every expansion. - Memory impact: none. - Speed impact: slight penalty, due to more bookkeeping. - * m4/m4module.h (m4_push_string_init): Add parameters. - * m4/m4private.h (struct m4_macro_args): Remove argv0 and - argv0_len, now redundant with info. - (m4__push_wrapup_init): Add parameter. - * m4/input.c (m4_push_string_init, m4__push_wrapup_init): Track - location from caller, rather than context. - (composite_peek, composite_read, match_input): Adjust callers. - * m4/utility.c (m4_symbol_value_lookup): Quote macro name. - (m4_verror_at_line): Allow NUL in macro name. - * m4/macro.c (trace_flush, m4_trace_prepare, trace_pre): Allow NUL - in trace. - (expand_macro): No longer munge context location. - (collect_arguments, m4_arg_text, m4_arg_empty, m4_arg_len) - (m4_make_argv_ref, m4_push_arg, m4_wrap_args): Adjust callers. - * modules/gnu.c (builtin, indir): Likewise. - * tests/null.m4: Enhance test. - * tests/null.err: Adjust expected output. - * tests/null.out: Likewise. - - Stage 24b: Allow embedded NUL in macro names. - Use length rather than NUL-termination when tracking macro names. - All APIs dealing with symbol table changed. - Memory impact: none. - Speed impact: slight penalty, due to more bookkeeping. - * m4/m4module.h (m4_symtab_apply_func, m4_symbol_lookup) - (m4_symbol_pushdef, m4_symbol_define, m4_symbol_popdef) - (m4_symbol_rename, m4_symbol_delete): Add length parameter. - (m4_string): New type. - * ltdl/m4/gnulib-cache.m4: Import xmemdup0 module. - * m4/hash.c (m4_hash_string_hash, m4_hash_string_cmp): Account for - length. - * m4/symtab.c (m4_symtab_delete, m4_symtab_apply, symtab_fetch) - (m4__symtab_remove_module_references, symbol_destroy_CB) - (m4_symbol_lookup, m4_symbol_pushdef, m4_symbol_define) - (m4_symbol_popdef, m4_symbol_rename, m4_set_symbol_name_traced) - (m4_symbol_delete): Likewise. - * modules/m4.h (struct m4_dump_symbol_data): Adjust type to allow - passing length. - * m4/macro.c (expand_token): Adjust all callers. - * m4/module.c (install_builtin_table, install_macro_table): - Likewise. - * m4/utility.c (m4_symbol_value_lookup): Likewise. - * modules/gnu.c (indir, renamesyms, m4symbols): Likewise. - * modules/m4.c (define, undefine, pushdef, popdef) - (dumpdef_cmp_CB, dump_symbol_CB, m4_dump_symbols, dumpdef) - (traceon, traceoff): Likewise. - * src/main.c (main): Likewise. - * src/freeze.c (dump_symbol_CB, reload_frozen_state): Likewise. - * tests/freeze.at (reloading nul): Augment test. - * tests/null.out: Adjust expected output. - - Stage 24a: Use full call context in error reporting. - Replace const char *macro_name with const m4_call_info *call, so - that the next patch can pass the length of macro_name with - embedded NUL. Simplifies handling of global state. - Memory impact: none. - Speed impact: none noticed. - * m4/m4module.h (m4_error, m4_warn): Change parameter type. - (m4_error_at_line, m4_warn_at_line): Delete. - (m4_debug_set_output, m4_skip_line, m4_bad_argc, m4_numeric_arg) - (m4_parse_truth_arg, m4_symbol_value_lookup): Adjust all clients. - * m4/m4private.h (m4__next_token): Likewise. - * m4/utility.c (m4_verror_at_line): Alter parameter, and use - caller's location if caller is provided. - (m4_error, m4_warn): Change parameter type. - (m4_error_at_line, m4_warn_at_line): Delete. - (m4_bad_argc, m4_numeric_arg, m4_parse_truth_arg) - (m4_symbol_value_lookup): Adjust all callers. - * m4/debug.c (set_debug_file, m4_debug_set_output): Likewise. - * m4/input.c (m4_skip_line, m4__next_token): Likewise. - * m4/macro.c (expand_argument, collect_arguments, m4_macro_call) - (process_macro): Likewise. - * modules/m4.h (m4_make_temp_func): Likewise. - * modules/evalparse.c (m4_evaluate): Likewise. - * modules/format.c (arg_int, arg_long, arg_double, format): - Likewise. - * modules/gnu.c (builtin, changeresyntax, changesyntax, debugfile) - (debuglen, debugmode, esyscmd, indir, mkdtemp, patsubst, regexp) - (renamesyms, syncoutput, regexp_compile, substitute) - (regexp_substitute, m4_resyntax_encode_safe): Likewise. - * modules/m4.c (define, undefine, pushdef, popdef, ifdef, ifelse) - (m4_dump_symbols, defn, syscmd, incr, decr, divert, undivert, dnl) - (include, maketemp, mkstemp, m4exit, traceon, traceoff, substr): - Likewise. - * modules/stdlib.c (setenv, getpwuid, srand): Likewise. - * modules/time.c (ctime, gmtime, localtime, mktime, strftime): - Likewise. - * tests/options.at (--syncoutput): Add test for invalid - command-line argument. Split xfailed portion... - (--syncoutput and diversions): ...into new test. - (unknown option): New test. - * tests/freeze.at (reloading unknown builtin): Update expected - output. - - Adjust to recent gnulib change. - * configure.ac (AB_INIT): Delete, now that gnulib does this. - -2008-05-28 Eric Blake - - Improve frozen debugmode behavior. - * m4/debug.c (m4_debug_decode): Make empty debugmode additive. - * src/main.c (main): Interleave -d with files. - * tests/options.at (--debugmode): Update test. - * tests/freeze.at (reloading debugmode): New test. - * doc/m4.texinfo (Debugging options, Debugmode): Document the - change. - * NEWS: Likewise. - -2008-05-27 Eric Blake - - Fix some testsuite failures on Solaris 8. - * tests/builtins.at (esyscmd, syscmd): Skip tests if system(2) is - broken. - * tests/others.at (stderr closed): Likewise. Also support Solaris - wording for EBADF. - (stdin closed): Skip test if closed stdin gets reopened. - (stdout closed): Support Solaris wording for EBADF. - * tests/testsuite.at (AT_CHECK_M4): Likewise. - - Fix configure message nesting, broken since 2001-09-20. - * ltdl/m4/gmp.m4 (M4_LIB_GMP): Don't cache result; the test is - not expensive, and AC_MSG_WARN doesn't work in AC_CACHE_CHECK. - - Support 'make dist' with BSD make. - * Makefile.am (TESTSUITE_AT, MAINTAINERCLEANFILES): Qualify uses - of the generated file tests/generated.at. - (EXTRA_DIST, $(TESTSUITE)): Likewise for tests/package.m4. - * tests/others.at (stdout closed): Accomodate OpenBSD /bin/sh. - -2008-05-24 Eric Blake - - Test NUL in frozen files. - * tests/testsuite.at (AT_CHECK_M4): Add parameter. - * tests/freeze.at (reloading nul): New test. - (AT_TEST_FREEZE): Inhibit -d when reloading frozen file. - (reloading unknown builtin): Likewise. - -2008-05-23 Eric Blake - - Improve handling of frozen file errors. - * src/freeze.c (produce_frozen_state): Detect write failures. - (reload_frozen_state): Use close_stream. - * tests/freeze.at (freezing failure): New test. - * THANKS: Update. - Reported by Jean-Charles Longuet. - -2008-05-19 Eric Blake - - In frozen file, split consecutive strings with newline. - * src/freeze.c (dump_symbol_CB): Add newline to 'T', 'F'. - (produce_frozen_state): Likewise for 'Q', 'C'. - (reload_frozen_state): Parse the new layout. - [GET_DIRECTIVE]: Fix format 1 regression from 2008-05-13. - * tests/freeze.at (loading format 2): Rewrite to new format. - (reloading unknown builtin): Likewise. - (loading format 1): Make sure backslash-newline is not - interpreted. - * doc/m4.texinfo (Frozen file format 2): Document the format. - * NEWS: Document this change. - - Fix xgettext options. - * po/Makevars (XGETTEXT_OPTIONS): The " must be passed to - xgettext. - - Fix spelling of RenĂ© Seindal's name in --version output. - * ltdl/m4/gnulib-cache.m4: Import propername module. - * src/main.c (AUTHORS): Rewrite in terms of proper_name. - * po/Makevars (XGETTEXT_OPTIONS): Detect new functions. - * HACKING: Mention new prerequisite of gperf. - -2008-05-18 Eric Blake - - Allow freezing the trace status of macros. - * src/freeze.c (produce_symbol_dump): Let undefined traced macros - through. - (dump_symbol_CB): Also freeze trace state. - * tests/freeze.at (reloading traced macros): New test. - * doc/m4.texinfo (Using frozen files): Update documentation to - mention new state. - (Frozen file format 1): Improve synchronization with branch. - (Frozen file format 2): Reorder directives, and add `d', `t'. - * NEWS: Document this change. - -2008-05-15 Eric Blake - - Fix frozen file regression in pushdef stacks from 2001-09-01. - * src/freeze.c (dump_symbol_CB): Push all values on the stack, not - just the current definition. - (reverse_symbol_value_stack): New helper method. - * tests/freeze.at (AT_TEST_FREEZE): New helper macro. - (reloading pushdef stack): New test. - (reloading unknown builtin): Enhance test. - -2008-05-13 Eric Blake - - Fix frozen file regression in diversions from 2007-01-21. - * m4/output.c (insert_diversion_helper): Add parameter. - (m4_insert_file): Move contents... - (insert_file): ...to this new helper, with added parameter. - (m4_insert_diversion, m4_undivert_all, m4_freeze_diversions): - Update callers. - * src/freeze.c (produce_mem_dump): Simplify. - * tests/freeze.at (large diversion): Test for this. - - Improve error message when frozen file is invalid. - * src/freeze.c (decode_char): Add parameter. Allow \ - line continuations. - (reload_frozen_state): Track current line. - * tests/freeze.at (loading format 1, loading format 2): Update to - test this. - -2008-05-10 Eric Blake - - Detect integer overflow when loading frozen file. - * src/freeze.c (reload_frozen_state) [GET_NUMBER]: Rewrite to fail - immediately on overflow. - * tests/freeze.at (loading format 2): Test this. - Reported by Jim Meyering. - -2008-05-08 Eric Blake - - Stage 23: allow tracing of indirect macro calls. - Track all trace information as part of the argv struct, rather - than temporarily resetting global state. Teach indir to trace - macros that it invokes. - Memory impact: slight penalty, due to larger argv struct. - Speed impact: none noticed. - * m4/m4module.h (m4_input_block): Remove. - (m4_call_info): New opaque type. - (m4_trace_prepare, m4_arg_info): New prototypes. - (m4_macro_call, m4_push_string_finish, m4_input_print): Change - prototypes. - * m4/m4private.h (struct m4_macro_args): Add info field. - (struct m4_call_info): New structure. - (m4_arg_info): New accessor. - * m4/input.c (m4_input_block): Make typedef local. - (m4_push_string_init): Initialize length. - (m4_push_string_finish, m4_input_print): Change signature, so that - printing can be done before finalization. - (struct input_funcs): Add parameter to print_func. - (file_print, string_print, composite_print): Adjust accordingly. - * m4/macro.c (trace_header, trace_flush, trace_pre, trace_post): - Change signatures for stacked trace messages, and for using call - context. - (trace_prepre): Export and rename... - (m4_trace_prepare): ...to this, for use by indir. Alter signature - to use call context. - (collect_arguments): Alter signature, to manage new field. - (expand_macro): Change call context management. Move tracing... - (m4_macro_call): ...here. Remove redundant parameter. - (m4_arg_argc): New function. - (m4_make_argv_ref): Replace unused skip parameter with new trace - parameter; manage new field. - * modules/gnu.c (builtin, indir): Adjust callers. - * src/main.c (usage): Update debugmode flag summary. - * tests/null.m4: Enhance test. - * tests/null.err: Update expected output. - * tests/macros.at (Tracing Hanoi Towers): Likewise. - * doc/m4.texinfo (Trace): Mention more about trace formatting. - (Debugmode): Enhance description of 'c' and 'x'. Enhance test to - cover line numbering details in traces. - (Debuglen): Enhance test to cover indir tracing. - * NEWS: Mention these changes. - Reported by Akim Demaille in the autoconf TODO file in 2000. - -2008-05-07 Eric Blake - - Test for traceon regression just fixed in branch-1.6. - * doc/m4.texinfo (Trace): Enhance test. - * NEWS: Port news item from branch. - -2008-05-05 Eric Blake - - Stage 22: allow builtin token concatenation outside $@. - Adjust the input and argument parsing engines to append builtins - alongside text. Make define warn when builtins must be - flattened. - Memory impact: slight penalty, with fewer builtins flattened. - Speed impact: slight penalty, from more bookkeeping. - * m4/m4module.h (m4_is_arg_composite): New prototype. - (m4_symbol_value_copy): Change return type. - (m4_arg_text): Add parameter. - (M4ARG): Adjust callers. - * m4/m4private.h: Adjust comments. - * m4/symtab.c (m4_symbol_value_copy): Detect when builtins are - flattened. - * m4/input.c (init_builtin_token): Add parameter, and allow - concatenating builtins. - (m4__next_token): Adjust caller. - * m4/macro.c (m4_is_arg_composite): New function. - (expand_argument): Allow builtin concatenation. - (m4_arg_text): Add parameter. - (m4__arg_adjust_refcount, m4__arg_print): Adjust callers. - (m4_arg_equal): Fix comparison of builtin tokens. - * modules/m4.c (define, pushdef): Warn when flattening builtins. - * doc/m4.texinfo (Define): Remove dead comment. - (Defn): Update to reflect code changes. - * tests/builtins.at (defn): Remove xfail. - * NEWS: Document this change. - -2008-05-03 Eric Blake - - Document define_blind. - * doc/m4.texinfo (Ifelse): Add a new composite macro. - * THANKS: Update. - Suggested by Mike R. - -2008-05-01 Eric Blake - - Avoid -Wshadow compiler warnings. - * m4/output.c (threshold_diversion_CB): s/div/diversion/. - * m4/macro.c (make_argv_ref, arg_symbol, m4_arg_symbol) - (m4_is_arg_text, m4_is_arg_func, m4_arg_text, m4_arg_empty) - (m4_arg_len, m4_arg_func, m4__arg_print, m4_make_argv_ref) - (m4_push_arg, m4__push_arg_quote): s/index/arg/. - * modules/format.c (format): Likewise. - * modules/m4.c (ifelse): Likewise. - - Improve debugmode testing, based on recent branch-1.6 regressions. - * doc/m4.texinfo (Debugmode): Enhance tests. - * tests/generate.awk: Run tests from stdin, not input.m4. Support - stderr munging when using -I examples. - - Fix regression in define from 2008-02-22. - * m4/m4module.h (m4_symbol_value_copy): Add parameter. - * m4/symtab.c (m4_symbol_value_copy): Support copying $@ - back-references. - * m4/macro.c (expand_argument): Update callers. - * modules/m4.c (define, pushdef): Likewise. - * tests/builtins.at (define): Enhance test to catch this. - -2008-04-21 Eric Blake - - Simplify previous patch. - * tests/m4.in: Compress assignment. - Suggested by Gary V. Vaughan. - - Fix --disable-shared testsuite regression from previous patch. - * tests/m4.in: Export M4MODPATH, so that recursive m4 invocations - will also work. - - 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 - - Fix testsuite bug when SIGPIPE is ignored. - * tests/builtins.at (divert): Consume all of m4's output, to avoid - spurious write failure. - * src/main.c (main): In batch mode, restore default handling of - SIGPIPE. - * doc/m4.texinfo (Operation modes): Document SIGPIPE behavior. - * THANKS: Update. - Reported by Bob Proulx, via his autobuilder. - -2008-04-15 Eric Blake - - Fix 'make installcheck' after './configure --prefix-progname'. - * tests/testsuite.at (AT_CHECK_M4): Allow overriding the m4 - program name. - (HELP_OTHER, PREPARE_TESTS): Document and use $M4. - * tests/builtins.at (patsubst): Avoid space-tab. - (divert, mkdtemp, mkstemp): Adjust tests to use $M4. - * tests/options.at (--debugfile): Likewise. - * tests/others.at (stdin seekable): Likewise. - (fstab): Avoid space-tab. - * Makefile.am (installcheck-local): Accomodate transformed name. - (DISTCHECK_CONFIGURE_FLAGS): Ensure no regressions, by using gm4 - during 'make distcheck'. - * cfg.mk: New file, borrowed from branch. - - Update prerequisite tools to match recent releases. - * configure.ac (AC_PREREQ): Rely on released autoconf. - (LT_PREREQ): Rely on released libtool. - * tests/testsuite.at (m4_version_prereq): Update dependence. - * bootstrap: Mention prerequisites. - - Work around OS/2 limitation of printf(1). - * tests/null.m4: Use m4, not printf, to generate NUL byte. - * tests/null.out: Check for esyscmd failure. - Reported by Elbert Pol. - -2008-04-14 Eric Blake - - Stage 21b: $@ concatenates builtins, m4wrap takes builtins. - Improve arg_print to handle builtin tokens when printing to a - known chain, rather than always flattening builtins. This allows - m4wrap and $@ back-references to handle embedded builtin tokens. - Memory impact: none. - Speed impact: slight penalty, from more bookkeeping. - * m4/m4module.h (m4_push_builtin): Add parameter. - (m4_builtin_print, m4_push_wrapup_init, m4_push_wrapup_finish) - (m4_arg_print, m4_symbol_value_print): Rename and reduce scope... - * m4/m4private.h (m4__builtin_print, m4__push_wrapup_init) - (m4__push_wrapup_finish, m4__arg_print, m4__symbol_value_print): - ...to these, in some cases adding a parameter. - (m4__append_builtin): New prototype. - * m4/builtin.c (m4_builtin_print): Alter signature to print - builtin to a growing symbol chain. - * m4/symtab.c (m4__symbol_value_print): Alter signature. - (m4_symbol_print, dump_symbol_CB): Adjust callers. - * m4/input.c (builtin_peek, builtin_read, builtin_unget) - (builtin_print, builtin_funcs): Delete, handled via composite - blocks now. - (struct m4_input_block): Delete u.builtin member. - (init_builtin_token): Only use composite block. - (m4__append_builtin): New function. - (m4_push_builtin, m4__push_wrapup_init): Alter signature. - (m4__push_symbol): Allow builtin tokens. - (m4__push_wrapup_finish): Rename. - (composite_print, m4_print_token): Adjust callers. - * m4/macro.c (m4_wrap_args, collect_arguments): Allow builtin - tokens. - (m4__arg_print): Alter signature. - (trace_prepre, trace_pre, m4_arg_text, m4_arg_equal): Adjust - callers. - * modules/m4.c (m4wrap): Allow builtin tokens. - (defn, errprint): Adjust callers. - * modules/gnu.c (builtin): Likewise. - * doc/m4.texinfo (M4wrap): New test. - (Debuglen): Adjust expected output. - - Stage 21a: Optimize checks for end of input. - Create a new polymorphic input block type, which always fails with - CHAR_EOF, so that remaining input routines no longer have to check - for NULL input block. - Memory impact: none. - Speed impact: noticeable improvement, from fewer conditionals. - * m4/input.c (eof_funcs, input_eof): New objects. - (eof_peek, eof_read, eof_unget): New functions. - (file_clean, m4_push_string_init, pop_input, m4_push_wrapup_init) - (m4_pop_wrapup, next_char, peek_char, unget_input, m4_input_init) - (m4_input_exit): Use placeholder to guarantee non-NULL isp and - wsp. - (next_char): Rename retry to allow_unget, and change sense for - easier manipulation. All callers changed. - - Improve OS/2 detection. - * modules/gnu.c (m4_macro_table): Ensure all possible identifiers - are defined, not just the first. The testsuite ensures that - exactly one gets defined. - * m4/system_.h [__EMX__]: OS/2 is not Unix-compatible, no matter - what other pre-defined macros it has. - * THANKS: Update. - Reported by Elbert Pol. - - Ensure __m4_version__ is unquoted. - * tests/builtins.at (__m4_@&t@version__): Augment test. - - Avoid GNU make failure on tarball. - * Makefile.am (EXTRA_DIST): Distribute cfg.mk and maint.mk. - -2008-04-10 Eric Blake - - Allow back-referenced macro names; fixes 2008-03-13 regression. - * m4/m4module.h (m4_symbol_value_lookup): Change prototype. - * m4/utility.c (m4_symbol_value_lookup): Change signature. - * modules/m4.c (undefine, popdef, ifdef, m4_dump_symbols, defn): - Adjust all callers. - * tests/others.at (ifndef): New test. - - Be namespace clean for M4 version; fixes 2008-04-08 regression. - * configure.ac (version): Rename... - (M4_VERSION): ...to this, since using 'version' broke po.m4. - -2008-04-09 Eric Blake - - Mention 1.4.11 release. - * doc/m4.texinfo (History, Defn, Ifdef, Ifelse, M4wrap) - (Extensions, Improved foreach): Distinguish 1.4.11 and 1.6. - (Format): Add test of C99 hex-float parsing. - * NEWS: Mention 1.4.11 release. - * tests/builtins.at (divert): Add additional test. - -2008-04-08 Eric Blake - - Overhaul inter-version releases to work with git. - * configure.ac (version): New variable, which has nicer version - contents when using git 1.5.5+, hardcoded to 1.9a otherwise. - (TIMESTAMP): Delete, since CVS id expansion died with transition - to git. - (AM_INIT_AUTOMAKE): Use version to decide gnu vs. gnits. - * build-aux/mkstamp: Delete, no longer used. - * Makefile.am (CONFIG_STATUS_DEPENDENCIES): Kill, to speed up - rebuilds when timestamps don't matter. - (MKSTAMP): Delete, no longer used. - (EXTRA_DIST): No longer worry about mkstamp. - (.version): New rule and distributed file. - (doc/m4.1, tests/package.m4): Depend on .version, not - configure.ac, for timestamp. - * ltdl/m4/gnulib-cache.m4: Import git-version-gen module. - * modules/gnu.c (__m4_version__): TIMESTAMP no longer exists. - * src/main.c (main): Likewise. - -2008-03-28 Eric Blake - - Use GNUmakefile module. - * ltdl/m4/gnulib-cache.m4: Import gnumakefile module. - * Makefile.am: Split off maintainer rules... - * maint.mk: ...into this new file. - -2008-03-18 Eric Blake - - Stage 20b: make m4wrap obey POSIX fifo ordering. - Improve input engine to support location changes within symbol - chains, then convert m4wrap to always build symbol chain. - Memory impact: none. - Speed impact: slight penalty, from more m4wrap bookkeeping. - * m4/m4module.h (m4_wrap_args): Add prototype. - * m4/m4private.h (enum m4__symbol_chain_type): Add M4__CHAIN_LOC. - (struct m4__symbol_chain): Add struct u_l. - * m4/input.c (m4_push_wrapup_init, m4_push_wrapup_finish): Use - new link type. - (composite_peek, composite_read, composite_clean): Handle location - link. - * m4/macro.c (m4_wrap_args): New function. - * modules/m4.c (m4wrap): Use it. - * doc/m4.texinfo (M4wrap): Sync with branch and POSIX. - (Extensions): Document extension of multiple arguments. - (Location, Improved m4wrap): Adjust example to match FIFO order. - * tests/builtins.at (wrap): Likewise. - * NEWS: Document this change. - -2008-03-17 Eric Blake - - Stage 20a: reduce unget's in input engine. - Now that out-of-range input placeholders like CHAR_BUILTIN are - consumed outside of next_char, next_token should always consume - rather than peek at the first character. Fewer peeks results in - less ungetc overhead. - Memory impact: none. - Speed impact: noticeable improvement, from fewer function calls. - * m4/input.c (struct input_funcs): Alter read_func prototype. - (next_char, file_read, buildin_read, string_read, composite_read): - Add allow_argv parameter. - (init_builtin_token, init_argv_symbol): Require all prior input to - be consumed. - (m4_skip_line, match_input, consume_syntax): Adjust callers. - (m4__next_token): Consume first byte without peek. - - Update for fresh bootstrap. - * ltdl/m4/gnulib-cache.m4: Updated copyright from upstream. - -2008-03-15 Eric Blake - - Document join, in order to fix bug in m4wrap example. - * examples/join.m4: New file. - * examples/wraplifo2.m4: Likewise. - * Makefile.am (EXTRA_DIST): Add new files. - * doc/m4.texinfo (Improved m4wrap): New node. - (Defn, Location): Enhance tests. - (Shift): Document the composite macro join. - (Incompatibilities): Move documentation of LIFO vs. FIFO... - (M4wrap): ...here, to match improved example. - -2008-03-13 Eric Blake - - Stage 19c: allow builtin tokens in more macros. - Allow builtin tokens inside symbol chains, although for now, they - are not allowed inside comments or quotes. Enable builtin token - handling in more macros, if only to consistently diagnose invalid - macro names. - Memory impact: none. - Speed impact: slight impact, due to more bookkeeping. - * m4/m4module.h (m4_symbol_value_lookup, m4_builtin_print): New - prototypes. - * m4/m4private.h (enum m4__symbol_chain_type): Add - M4__CHAIN_FUNC. - (struct m4__symbol_chain): Add builtin member. - * m4/utility.c (m4_symbol_value_lookup): New method. - * m4/builtin.c (m4_builtin_print): New function. - * m4/symtab.c (m4_symbol_value_print): Use it. - * m4/input.c (builtin_print): Likewise. - (m4__push_symbol): Allow pushing builtin tokens. - (composite_peek, composite_read, composite_unget, composite_clean) - (composite_print): Handle builtin tokens. - (init_builtin_token): Allow builtin tokens from composite input. - (m4__next_token): Flatten builtins inside comment or string. - * m4/macro.c (expand_argument): Strengthen assertion. - (collect_arguments, m4_arg_equal, m4_arg_print, m4_push_args): - Handle builtin tokens. - (arg_symbol): Add parameter, and allow NULL level. - (m4_arg_symbol, m4__push_arg_quote): Adjust callers. - (m4_arg_text): Ensure all builtins have been flattened. - * modules/m4.c (defn, dumpdef, popdef, traceoff, traceon) - (undefine, m4_dump_symbols): Warn on invalid macro names. - (ifdef, ifelse, shift): Handle builtin tokens. - * modules/gnu.c (m4symbols): Likewise. - * doc/m4.texinfo (Defn, Ifdef, Ifelse): Document and test the new - behavior. - (Debuglen): Likewise, and remove xfail. - * NEWS: Mention the change. - - Stage 19b: invert sense of bit for handling builtin tokens. - Pass builtin tokens by default, rather than as the exception, so - that the logic can consistently refer to flattening arguments. - Memory impact: none. - Speed impact: none. - * m4/m4module.h (M4BUILTIN_ENTRY): New convenience macro. - (M4_BUILTIN_GROKS_MACRO): Rename... - (M4_BUILTIN_FLATTEN_ARGS): ...and invert sense. - (m4_symbol_value_groks_macro, m4_symbol_groks_macro): Likewise... - (m4_symbol_value_flatten_args, m4_symbol_flatten_args): ...to - this. - * m4/m4private.h (VALUE_MACRO_ARGS_BIT) - (m4_symbol_value_groks_macro): Likewise... - (VALUE_FLATTEN_ARGS_BIT, m4_symbol_value_flatten_args): ...to - this. - * m4/symtab.c (m4_symbol_value_groks_macro): Likewise... - (m4_symbol_value_flatten_args): ...to this. - * m4/macro.c (collect_arguments): Accomodate changed sense. - * m4/module.c (m4__module_open): Require arguments if flattening - is requested. - * m4/input.c (m4_push_string_finish): For now, flatten all - builtins pushed as back-references. - * modules/gnu.c (m4_builtin_table, builtin): Adjust all clients. - * modules/import.c (m4_builtin_table): Likewise. - * modules/load.c (m4_builtin_table): Likewise. - * modules/modtest.c (m4_builtin_table): Likewise. - * modules/mpeval.c (m4_builtin_table): Likewise. - * modules/perl.c (m4_builtin_table): Likewise. - * modules/shadow.c (m4_builtin_table): Likewise. - * modules/stdlib.c (m4_builtin_table): Likewise. - * modules/time.c (m4_builtin_table): Likewise. - * modules/m4.c (m4_builtin_table): Likewise. - (mkstemp): Undo #undef hack from 2006-10-23, now that macro names - are stringized without preprocessor expansion. - * doc/m4.texinfo (Defn): Update comments to match reality. - (Debuglen): Update test now that user macros pass builtin tokens. - - Stage 19a: sort and cache builtins loaded by a module. - Rather than repeatedly using dlsym to browse the builtin table, - copy off the table at module load time. Then, the input engine - merely refers to the copy instead of duplicating information. - Memory impact: slight penalty, due to more memory per module, but - offset by less memory in input engine. - Speed impact: slight improvement, due to faster builtin lookups. - * m4/m4module.h (m4_set_symbol_value_builtin): Delete. Use - m4_builtin_find_by_* instead. - (m4_builtin_find_by_func): Change return type. - * m4/m4private.h (m4__builtin): New struct. - (m4_module): Add sorted list of loaded builtins. - (struct m4_symbol_value): Change type of builtin value. - (m4__set_symbol_value_builtin): New prototype and fast accessor. - (m4_get_symbol_value_func, m4_get_symbol_value_builtin): Adjust to - new field type. - * m4/symtab.c (m4_set_symbol_value_builtin): Rename... - (m4__set_symbol_value_builtin): ...and populate additional fields, - based on new type. - (m4_get_symbol_value_func, m4_get_symbol_value_builtin): Adjust to - new field type. - * m4/module.c (install_builtin_table): Use cached table. - (compare_builtin_CB): New helper function. - (m4__module_open): Populate table. - (module_remove): Free table. - * m4/builtin.c (compare_builtin_name_CB): New helper function. - (m4_builtin_find_by_name): Rewrite to use sorted table. - (m4_builtin_find_by_func): Change return type. - * m4/input.c (struct m4_input_block): Simplify u_b, since most - fields can be determined from builtin. - (builtin_peek, builtin_read, builtin_unget, init_builtin_token) - (m4__next_token): Alter parsing so that only init_builtin_token - consumes a builtin. - (builtin_print, m4_push_builtin): Adjust all users. - * tests/macros.at (Arity, defn, and freeze): Fix typo. - - Consistently cast malloc results, for C++ compilation. - * m4/builtin.c (m4_builtin_find_by_name): Add cast. - * m4/hash.c (m4_hash_new, m4_get_hash_iterator_next, node_new) - (m4_hash_resize, maybe_grow): Likewise. - * m4/m4.c (m4_create): Likewise. - * m4/macro.c (expand_macro): Likewise. - * m4/output.c (m4_tmpname): Likewise. - * m4/path.c (search_path_add): Likewise. - * m4/symtab.c (m4_symtab_create, m4_symbol_value_create) - (symtab_fetch): Likewise. - * m4/syntax.c (m4_syntax_create): Likewise. - * modules/gnu.c (regexp_compile): Likewise. - * src/main.c (main): Likewise. - * src/freeze.c (reload_frozen_state): Likewise. - -2008-03-06 Eric Blake - - Fix nested builtin(`shift',$@) regression from 2008-02-23. - * m4/macro.c (make_argv_ref): Don't output expansion text when - making wrapper for builtin or indir. - * tests/builtins.at (builtin): New test. - * NEWS: Document the fix. - Reported by Andreas Schwab. - -2008-03-04 Eric Blake - - The gnulib module free was deprecated. - * ltdl/m4/gnulib-cache.m4: Remove free module. - -2008-02-29 Eric Blake - - Import news from 1.4.10b. - * NEWS: Update from branch. - -2008-02-23 Eric Blake - - Stage 18: try harder to reuse argv in recursion. - When pushing arguments that contain an existing $@ ref, reuse the - ref rather than creating another layer of wrappers. - Memory impact: noticeable improvement, due to better $@ reuse. - Speed impact: noticeable improvement, due to O(n^2) to O(n) - reduction in unboxed recursion. - * m4/macro.c (make_argv_ref): Avoid wrapping $@ when possible. - (m4_push_args): Let make_argv_ref take care of pending data. - * doc/m4.texinfo (Improved foreach): Tweak wording to match new - performance capability. - * tests/others.at (recursion): Add tests to avoid performance - regression. - -2008-02-22 Eric Blake - - Update NEWS. - * NEWS: Document change to __gnu__ on 2008-02-11. - - Stage 17: pass argv through quoted strings. - Allow the concatenation of $@ references with other text input - inside quoted contexts, which requires distinguishing between a - wrapper around many arguments vs. a reference serving as part of a - single argument. Also optimize based on whether argv contains - builtin tokens that might need flattening to the empty string. - Memory impact: noticeable improvement, due to O(n^2) to O(n) - reduction from total reuse of $@ references. - Speed impact: noticeable improvement, due to O(n^2) to O(n) - reduction in boxed recursion. - * m4/m4module.h (m4_arg_equal, m4_arg_len): Add parameter. - (M4ARGLEN): Adjust definition. - * m4/m4private.h (struct m4__symbol_chain): Add has_func member. - (struct m4_symbol_value): Add wrapper and has_func members. - (struct m4_macro_args): Add flatten and has_func members. - * m4/input.c (append_quote_token): Return argv refs inside quoted - strings. - (init_argv_symbol): Populate new fields. - * m4/macro.c (expand_argument, collect_arguments, make_argv_ref) - (m4_make_argv_ref): Likewise. - (arg_symbol, arg_mark, m4_is_arg_text, m4_is_arg_func): Use new - fields. - (m4_arg_equal, m4_arg_len): Handle quoted argv references, and add - new parameter. - * modules/m4.c (ifelse): Adjust caller. - -2008-02-22 Gary V. Vaughan - - Fix regression in argument collection, from 2008-01-21. - * m4/input.c (m4__next_token): When DEBUG_INPUT is defined, - undo argument collection optimisation for strings, so that - m4_print_token doesn't abort when it otherwise receives an - unprintable M4_SYMBOL_VOID type token. - -2008-02-20 Eric Blake - - Stage 16: cache quotes and improve m4_arg_print. - Cache rather than always copying quotes when pushing $@ refs; in - particular, reconstruct single-byte quotes on the fly. Allow NUL - through m4wrap. Improve sharing of code that prints arguments. - Memory impact: slight improvement, due to cached quotes. - Speed impact: slight improvement, due to less copying. - * m4/m4module.h (m4_symbol_value_print, m4_symbol_print) - (m4_arg_print): Adjust prototypes. - (m4_dump_args): Delete. - (m4_push_wrapup): Split... - (m4_push_wrapup_init, m4_push_wrapup_finish): ...into these - prototypes. - * m4/m4private.h (struct m4_syntax_table): Add cached_quote - member. - (m4__quote_cache, m4__quote_uncache): New prototypes. - * m4/syntax.c (m4_syntax_create): Initialize the cache. - (m4__quote_cache): New function. - (m4_set_syntax): Update caller. - * m4/symtab.c (m4_symbol_value_print): Add parameter. - (m4_symbol_print, dump_symbol_CB): Adjust all callers. - * m4/utility.c (m4_dump_args): Delete; callers should use - m4_arg_print instead. - * m4/input.c (m4_push_wrapup_init, m4_push_wrapup_finish): Split - implementation, and allow embedded NUL. - (m4_print_token, pop_input, composite_print, composite_peek): - (composite_read, append_quote_token): Adjust all callers. - * m4/macro.c (trace_prepre, m4_arg_text, make_argv_ref): - Likewise. - (m4_arg_print): Add parameters. - (trace_pre): Rewrite in terms of m4_arg_print. - * modules/m4.c (errprint): Likewise. - (m4wrap): Rewrite to allow embedded NUL. - (dumpdef): Adjust caller. - * doc/m4.texinfo (Debuglen): Enhance debuglen test. - * tests/null.m4: Test for NUL in m4wrap. - * tests/null.out: Update expected output. - - Fix out-of-bounds read for sanitized macro names, from 2008-02-06. - * m4/utility.c (m4_verror_at_line): Properly terminate the string. - Reported by Ralf Wildenhues. - - * doc/m4.texinfo (Debuglen, Changesyntax): Fix typos. - -2008-02-19 Eric Blake - - Clean up example on filtering defined symbols. - * doc/m4.texinfo (Foreach, Improved foreach): Document another - shortcoming in foreach.m4, and improve filter example by using - foreach2.m4. - - * src/main.c (usage): Fix typo. - -2008-02-18 Eric Blake - - Avoid some magic numbers. - * m4/m4private.h (CHAR_EOF, CHAR_BUILTIN, CHAR_QUOTE, CHAR_ARGV) - (CHAR_RETRY): Define in terms of UCHAR_MAX. - * m4/syntax.c (m4_syntax_create, set_syntax_set) - (reset_syntax_set, check_is_single_quotes) - (check_is_single_comments, check_is_macro_escaped) - (m4_set_quotes, m4_set_comment): Likewise. - * modules/gnu.c (regexp_compile): Likewise. - * modules/m4.c (translit): Likewise. - * src/freeze.c (produce_syntax_dump): Likewise. - Reported by Ralf Wildenhues. - -2008-02-16 Eric Blake - - Add regression test for multi-character quote recursion. - * examples/foreach2.m4: Use $0 rather than spelling out name. - * examples/foreachq2.m4: Likewise. - * examples/forloop2.m4: Likewise. - * examples/hanoi.m4: Likewise. - * examples/trace.m4: Likewise. - * doc/m4.texinfo (Improved forloop): Document advantage of $0. - (Improved foreach): Adjust dump from file. - - Stage 15: return argv refs back to collect_arguments. - Collect an entire $@ reference at once rather than one argument at - a time, outside of quotes (but inside quotes, $@ is still - flattened for now). The skip_last field allows concatenation of - $@ with other text when collecting arguments. - Memory impact: noticeable improvement, due to better reuse of $@. - Speed impact: noticeable improvement, due to less parsing. - * m4/m4private.h (CHAR_ARGV): New input engine sentinel. - (enum m4__token_type): Add M4_TOKEN_ARGV. - (struct m4__symbol_chain): Add skip_last member to argv link. - (m4__next_token): Add parameter. - * m4/input.c (peek_char, file_peek, builtin_peek, string_peek) - (composite_peek, m4__next_token): Add new parameter. - (composite_read, append_quote_token): Support argv in quotes. - (init_argv_symbol): New function. - (m4__push_symbol, match_input, consume_syntax) - (m4__next_token_is_open, m4_print_token): Adjust callers. - * m4/macro.c (m4_macro_expand_input, m4__arg_adjust_refcount) - (arg_mark, m4_arg_text, make_argv_ref): Likewise. - (expand_argument, collect_arguments): Handle new token. - (arg_symbol): Drill through $@ reference. - * m4/syntax.c (set_quote_age): Detect disabled comments. - * m4/symtab.c (dump_symbol_CB) [DEBUG_SYM]: Fix debug code. - -2008-02-15 Eric Blake - - * modules/gnu.c (regexp_compile): Use a fastmap for regex speed. - -2008-02-13 Eric Blake - - Fix texinfo grammar. - * doc/m4.texinfo (Eval, Incompatibilities): Use @. after capital. - (History): Use @: after abbreviations. - (M4exit): Use correct Latin abbreviation. - (Dumpdef, Debugmode, Frozen file format 2): Use correct spacing - between sentences. - -2008-02-11 Eric Blake - - Allow builtin text macros to specify number of arguments. - * m4/m4module.h (struct m4_macro): Add argument limits to builtin - text macros. - * m4/module.c (install_macro_table): Allow text macros to warn on - extra arguments. - * modules/gnu.c (m4_macro_table): Update all clients. - * modules/load.c (m4_macro_table): Likewise. - * modules/mpeval.c (m4_macro_table): Likewise. - * modules/perl.c (m4_macro_table): Likewise. - * modules/shadow.c (m4_macro_table): Likewise. - * modules/traditional.c (m4_macro_table): Likewise. - * modules/modtest.c (m4_macro_table): Likewise. Also add text - macros, for testing this. - * doc/m4.texinfo (Standard Modules): Update text, and enhance - test. - * tests/modules.at (modules: text): New test. - - Fix regression in command line -D option, from 2006-08-25. - * m4/m4private.h (m4_symbol_value_create): Delete fast accessor. - * m4/m4module.h: Fix typo. - * m4/symtab.c (m4_symbol_value_create): Prime the maximum number - of arguments. - * tests/macros.at (Command line define): Enhance test. - * tests/others.at (nul character): Enhance test. - * tests/null.m4: Likewise. - * tests/null.out: Likewise. - - Use gnulib's git-merge-changelog driver when available. - * .gitattributes: Add merge attributes for ChangeLog. - * bootstrap: Install driver, if not already present. - -2008-02-06 Eric Blake - - Fix security hole introduced 2007-11-23. - * m4/utility.c (m4_verror_at_line): Properly escape macro names. - * src/main.c (main): Manage quoteargs defaults. - * doc/m4.texinfo (Indir): Document and test this. - - Using raw strtod is not portable. - * ltdl/m4/gnulib-cache.m4: Import the strtod module. - -2008-02-02 Eric Blake - - Consistently use size_t for number of arguments. - * m4/m4module.h (m4_builtin_func): Alter prototype. - (struct m4_builtin): Adjust type of min_args, max_args. - (M4BUILTIN, M4BUILTIN_HANDLER): Adjust all builtins. - (m4_bad_argc, m4_dump_args, m4_macro_call, m4_arg_argc) - (m4_arg_symbol, m4_is_arg_text, m4_is_arg_func, m4_arg_text) - (m4_arg_equal, m4_arg_empty, m4_arg_len, m4_arg_func) - (m4_arg_print, m4_push_arg): Adjust all clients. - * m4/m4private.h (struct m4__symbol_chain, m4_symbol_value) - (m4_macro_args): Adjust type of various fields. - (m4__push_arg_quote): Adjust all clients. - * m4/input.c (m4_pop_wrapup): Likewise. - * m4/macro.c (m4_macro_call, trace_pre, make_argv_ref) - (arg_symbol, m4_arg_symbol, m4_is_arg_text, m4_is_arg_func) - (m4_arg_text, m4_arg_equal, m4_arg_empty, m4_arg_len) - (m4_arg_func, m4_arg_print, m4_make_argv_ref, m4_push_arg) - (m4__push_arg_quote, m4_push_args, m4_arg_argc): Likewise. - * m4/utility.c (m4_bad_argc, m4_dump_args): Likewise. - * modules/evalparse.c (m4_evaluate): Likewise. - * modules/gnu.c (changesyntax): Likewise. - * modules/m4.c (m4_dump_symbols, undefine, popdef, ifelse, defn) - (undivert, traceon, traceoff): Likewise. - * modules/m4.h (m4_dump_symbols_func): Likewise. - * modules/perl.c (perleval): Likewise. - - Stage 14b: allow pushing argv references. - Push a $@ reference to the input engine in one go, rather than - pushing each element. For now, argument collection still gets one - argument of a $@ at a time; but the penalties of this patch make - it easier to manage $@ efficiently in future patches. - Memory impact: noticeable penalty, due to larger struct and O(n) - to O(n^2) on unboxed recursion. - Speed impact: noticeable penalty, due to more bookkeeping. - * m4/m4private.h (struct m4__symbol_chain): Add comma and quotes - fields. - (struct m4_macro_args): Add level field. - (m4__arg_adjust_refcount, m4__push_arg_quote): New prototypes. - * m4/input.c (m4__push_symbol, composite_peek, composite_read) - (composite_unget, composite_clean, composite_print): Support $@ - refs. - * m4/macro.c (collect_arguments): Populate new field. - (expand_macro): Move argv cleanup... - (m4__arg_adjust_refcount): ...to this new function. - (m4_arg_symbol, m4_make_argv_ref, m4_push_arg): Factor... - (arg_symbol, make_argv_ref, m4__push_arg_quote): ...to these new - helper functions, to add parameters. - (m4_push_args): Adjust caller. - * m4/symtab.c (m4_symbol_value_print): Likewise. - - Stage 14a: allow printing argv references. - Refactor symbol-value printing code for better sharing, and to - allow printing a contiguous text representation of a $@ ref. - Memory impact: none. - Speed impact: none. - * m4/m4module.h (m4_arg_print): New prototype. - (m4_symbol_value_print): Alter prototype. - * m4/input.c (struct input_funcs): Add parameter to peek_func. - (file_peek, builtin_peek, string_peek): Ignore new parameter. - (composite_peek): Ignore new parameter, for now. - (composite_clean, pop_input): Rework to minimize indirection, and - to avoid infinite recursion in next patch. - * m4/macro.c (trace_prepre, trace_pre): Adjust callers. - (m4_arg_print): New function. - * m4/symtab.c (m4_symbol_value_print): Update signature. - (m4_symbol_print): Update caller. - * m4/output.c (m4_shipout_string_trunc): Update comments. - * m4/syntax.c (set_quote_age): Require comma as argument separator - when dealing with $@ as a unit. - * tests/builtins.at (ifelse): Augment test. - * doc/m4.texinfo (Changesyntax): Document changesyntax deficiency. - -2008-01-31 Eric Blake - - Kill hack for M4 1.4.4. - * configure.ac (AM_GNU_GETTEXT_INTL_SUBDIR): Delete, now that - we require new enough autoconf which in turn requires M4 1.4.5. - -2008-01-31 Gary V. Vaughan - and Eric Blake - - Depend on new libtool to use non-recursive build. - * configure.ac (LT_PREREQ): Bump to alpha release version. - (LTDL_INIT): Choose nonrecursive mode. Perform sanity check that - installed libtool has correct symbols. - * Makefile.am (SUBDIRS): Drop ltdl, now that it is built from the - top level. - (AM_CPPFLAGS): Drop directories covered by libtool. - (AM_LDFLAGS): Drop -no-undefined, covered by libtool. - (include_HEADERS, noinst_LTLIBRARIES, EXTRA_LTLIBRARIES): New - macros, used by libtool. - (lib_LTLIBRARIES): Also used by libtool. - (ltdl/libltdlc.la): Delete, now that libtool does this. - * bootstrap: Mention new requirements. - (LIBTOOLIZE): Provide default program, and run libtoolize prior to - autoreconf. - (autoreconf): Also neutralize libtoolize, since it is run early. - * HACKING: Mention updated prerequisites. - -2008-01-28 Ralf Wildenhues - - Fix build failure if installed libltdl is used. - * Makefile.am (m4_libm4_la_DEPENDENCIES): Use $(LTDLDEPS). - -2008-01-28 Eric Blake - - Depend on newer autoconf, for testsuite -C dir. - * Makefile.am (CD_TESTDIR): Delete, no longer required. - (check-local, installcheck-local, clean-local-tests): Use new -C - option from autotest. - * configure.ac (AC_PREREQ): Bump to 2.61a.347. - * bootstrap: Mention new dependency. - * HACKING: Likewise. - -2008-01-27 Eric Blake - - Stage 13: push composite text tokens. - Support pushing composite tokens, allowing back-references to be - reused through multiple macro expansions. Add hueristic that - avoids creating new reference when pushing existing references. - Memory impact: noticeable improvement due to better reference - reuse, except for O(n) to O(n^2) copying in boxed recursion. - Speed impact: slight penalty, due to more bookkeeping. - * m4/m4private.h (m4__push_symbol): Adjust prototype. - * m4/input.c (m4__push_symbol): Add parameter, and support - composite tokens. - (append_quote_token): Add parameter, and support inlining of short - text. - (m4__next_token): Adjust caller. - * m4/macro.c (m4_push_arg, m4_push_args): Likewise. - -2008-01-26 Eric Blake - - Stage 12c: add macro for m4_arg_len. - Make a common action easier to type. - Memory impact: none. - Speed impact: none. - * m4/m4module.h (M4ARGLEN): New macro. - * m4/macro.c (process_macro): Adjust all callers. - * m4/utility.c (m4_dump_args): Likewise. - * modules/m4.c (divert, maketemp, mkstemp, m4wrap, len, index) - (substr): Likewise. - * modules/gnu.c (builtin, indir, mkdtemp, patsubst, regexp) - (renamesyms): Likewise. - * modules/stdlib.c (setenv): Likewise. - - Stage 12b: add m4_string_pair. - Make passing quote delimiters around more efficient. - Memory impact: none. - Speed impact: slight penalty, due to more bookkeeping. - * m4/m4module.h (m4_string_pair): New type. - (m4_get_syntax_quotes, m4_get_syntax_comments): New prototypes. - (m4_symbol_value_print, m4_symbol_print, m4_shipout_string_trunc): - Alter signature. - * m4/m4private.h (struct m4_string): Delete. - (struct m4_syntax_table): Combine quote and comment members. - (m4_get_syntax_lquote, m4_get_syntax_rquote, m4_get_syntax_bcomm) - (m4_get_syntax_ecomm): Adjust accessors. - (m4_get_syntax_quotes, m4_get_syntax_comments): New fast - accessors. - * m4/symtab.c (m4_symbol_value_print, m4_symbol_print): - Alter signatures. - * m4/input.c (string_print, composite_print, m4_input_print): - All callers updated. - * m4/syntax.c (m4_syntax_delete, m4_set_syntax) - (check_is_single_quotes, m4_set_quotes, set_quote_age) - (m4_get_syntax_lquote, m4_get_syntax_rquote) - (m4_get_syntax_quotes, check_is_single_comments, m4_set_comment) - (m4_get_syntax_bcomm, m4_get_syntax_ecomm) - (m4_get_syntax_comments): Likewise. - * m4/macro.c (trace_prepre, trace_pre, m4_push_args): Likewise. - * m4/output.c (m4_shipout_string, m4_shipout_string_trunc): - Likewise. - * modules/m4.c (dumpdef, m4_make_temp): Likewise. - * src/freeze.c (produce_frozen_state): Likewise. - * tests/freeze.at (reloading unknown builtin): Update test. - - Stage 12a: make m4_symbol_chain a union. - Shrink size of symbol chains by using a union. - Memory impact: slight improvement, due to smaller struct. - Speed impact: slight improvement, due to less bookkeeping. - * m4/m4private.h (enum m4__symbol_chain_type): New enum. - (struct m4_symbol_chain): Rename... - (struct m4__symbol_chain): ...to this, since it is internal. - * m4/symtab.c (m4_symbol_value_copy, m4_symbol_value_print): All - callers updated. - * m4/input.c (struct m4_input_block, m4__push_symbol) - (composite_peek, composite_read, composite_unget) - (composite_clean, composite_print, m4__make_text_link) - (append_quote_token): Likewise. - * m4/macro.c (expand_macro, arg_mark, m4_arg_symbol, m4_arg_text) - (m4_arg_equal, m4_arg_len, m4_make_argv_ref, m4_push_arg) - (m4_push_args): Likewise. - -2008-01-23 Eric Blake - - Adjust to recent libtool interface change. - * configure.ac (LT_PREREQ): Require bleeding-edge libtool. - (LT_WITH_LTDL): Delete, now that it is obsolete. - (LTDL_INIT): Use new libtool macro. - -2008-01-22 Ralf Wildenhues - and Eric Blake - - Rely on newer automake. - * configure.ac (AM_INIT_AUTOMAKE): Require 1.10.1, and add lzma - distribution. - * bootstrap: Update automake requirement. - (func_version): Fix --version output, broken since 2007-08-06. - * HACKING: Likewise. Add lzma requirement. - * Makefile.am (clean-local-src): Not needed any more with newest - Automake. - (clean-local): Adjust. - * TODO: Remove completed item. - -2008-01-22 Eric Blake - - Doc tweak. - * doc/m4.texinfo (Renamesyms): Avoid underfull hbox, and improve - example. - -2008-01-21 Eric Blake - - Stage 11: full circle for single argument references. - Pass quoted strings through to argument collection in a single - action, so that an argument can be reused throughout macro - recursion if it remains unchanged. - Memory impact: noticeable improvement, due to more reuse in - argument collection stacks; O(n^2) to O(n) on boxed recursion. - Speed impact: noticeable improvement, due to less copying. - * m4/m4module.h (m4_arg_text): Add parameter. - (M4ARG): Adjust. - * m4/m4private.h (CHAR_QUOTE): New input engine sentinel. - (m4__make_text_link): New prototype. - (struct m4_symbol_chain): Add quote_age member. - (struct m4_symbol_value): Add end member to chained symbol. - (struct m4_macro_args): Add wrapper member. - * m4/symtab.c (m4_symbol_value_print): Print composite tokens. - (m4_symbol_value_copy, m4_symbol_value_delete): Recognize - composite tokens. - * m4/input.c (make_text_link): Rename... - (m4__make_text_link): ...to this, and export. - (m4_push_string_finish): Adjust caller. - (make_text_link, m4__push_symbol): Update new field. - (file_read, builtin_read, string_read, composite_read, next_char): - Add parameter. - (m4_skip_line, match_input, consume_syntax): Adjust callers. - (append_quote_token): New function. - (m4__next_token): Pass quoted strings onto argument collection. - (m4_print_token) [DEBUG_INPUT]: Update. - * m4/macro.c (expand_argument): Collect composite arguments. - (collect_arguments): Update new field. - (expand_macro): Reduce ref-count of back-references after use. - (arg_mark, m4_arg_symbol, m4_make_argv_ref): Adjust to new member - names. - (m4_is_arg_text): Also recognize composite symbols as text. - (m4_arg_text, m4_arg_len): Merge composite symbols as needed. - (m4_arg_equal): Compare composite symbols. - (m4_push_arg, m4_push_args): Handle composite symbols. - (m4_arg_symbol): Relax assertion. - (process_macro): Use single-argument references. - * m4/output.c (m4_shipout_string_trunc): Update comment. - * tests/macros.at (Rescanning macros): Augment test. - -2008-01-16 Eric Blake - - Stage 10: avoid extra copying of strings and comments. - When collecting tokens that are immune to further expansion, avoid - copying data from one obstack to another by outputting it into the - destination obstack to begin with. Also reduce copying done in - format builtin. - Memory impact: slight improvement, due to better obstack usage. - Speed impact: noticeable improvement, due less data copying. - * ltdl/m4/gnulib-cache.m4: Import intprops and vasnprintf-posix - modules. - * m4/m4private.h (m4__token_type): Adjust prototype. - * m4/input.c (m4__next_token): Support new parameter. - * m4/macro.c (m4_macro_expand_input, expand_token) - (expand_argument, collect_arguments): Adjust callers. - * modules/m4.c (ntoa): Tighten buffer size. - * m4/output.c (m4_tmpname): Guarantee no buffer overflow. - * modules/format.c (arg_int, arg_long, arg_double): New helper - functions, to detect overflow or unparsed characters. - (ARG_INT, ARG_LONG, ARG_STR, ARG_DOUBLE): Adjust to check for - missing or excess arguments. - (format): Likewise, and also output directly into obstack if there - is room. - * doc/m4.texinfo (History): Update for new year. - (Format): Test for new warnings. - -2008-01-15 Eric Blake - - * TODO: Update with some newer URLs. - - Verify linear `index'. - * tests/builtins.at (index): New test. - (translit): Make test take longer, to make quadratic algorithms - more apparent. - -2007-12-20 Eric Blake - - Stage 9: share rather than copy single-arg refs. - Use hooks of previous patch to create back-references to arguments - in the input engine, and inline short text rather than always - creating a FIFO link. Also start testing embedded NUL behavior. - Until the argument collection engine also shares references, the - memory usage increases. - Memory impact: noticeable penalty, due to longer life of argv - changing O(n) to O(n^2) on boxed recursion. - Speed impact: slight improvement, due less data copying. - * ltdl/m4/gnulib-cache.m4: Import memmem and quote modules. - * m4/m4module.h (m4_arg_scratch): New prototype. - * m4/m4private.h (m4__push_symbol): Add parameter. - (m4_arg_scratch): Add fast accessor. - (struct m4): Add expansion_level member, taken... - * m4/macro.c (expansion_level): ...from here. Adjust all users. - (expand_argument): Minor cleanup. - (expand_macro): Track scratch space per macro call. - (m4_arg_scratch): New function. - (m4_make_argv_ref): Call new function. - (m4_push_arg): Push reference to $0. - (m4_push_args): Rework separator usage, since separators will - usually be inlined. - (process_macro): Allow embedded NUL. - * m4/input.c (INPUT_INLINE_THRESHOLD): New define. - (m4__push_symbol): Add parameter. Inline short strings, and save - references through rescanning. - * m4/symtab.c (m4_set_symbol_value_text): Weaken assertion. - * modules/m4.c (errprint, index): Handle NUL transparently. - (dumpdef, translit): Use scratch space, rather than expansion - stack. - * modules/gnu.c (renamesyms, m4symbols): Likewise. - * tests/others.at (nul character): New test. - (iso8859): Quote absolute file name, remove XFAIL. - * tests/iso8859.m4: Avoid raw NUL in output. - * tests/null.m4: New file. - * tests/null.out: Likewise. - * tests/null.err: Likewise. - * Makefile.am (OTHER_FILES): Distribute new files. - * .gitattributes: Treat new files as text. - -2007-12-17 Eric Blake - - Stage 8: extend life of references into argv. - Add hooks to lengthen the lifetime of arguments reused in a macro - expansion, rather than always discarding arguments at the end of - expand_macro. Rework the expand_macro obstacks to handle longer - lifetimes. For now, the hooks remain unused. - Memory impact: slight penalty, due to larger structs. - Speed impact: slight penalty, due to more bookkeeping. - * m4/system_.h (obstack_regrow): Delete. - * m4/m4private.h (struct m4_symbol_chain): Add level field. - (m4__push_symbol): Adjust prototype. - (m4__adjust_refcount): New prototype. - (DEBUG_MACRO) [DEBUG]: New debug control. - (struct m4__macro_arg_stacks): New structure. - (struct m4): Add arg_stacks, stacks_count fields. - * m4/m4module.h (m4_make_argv_ref): Add parameter. - * m4/macro.c (argc_stack, argv_stack): Delete, replaced by - context->arg_stacks. - (m4_macro_expand_input) [DEBUG_MACRO]: Add debug hooks, - conditional on M4_DEBUG_MACRO envvar. - (collect_arguments): Adjust signature. - (expand_macro): Rework obstack handling. - (m4__adjust_refcount, arg_mark): New functions. - (m4_make_argv_ref): Populate new field. - (m4_push_arg, m4_push_args): Track inuse. - (process_macro): One less cast. - * m4/m4.c (m4_delete): Clean up arg_stacks. - * m4/input.c (make_text_link): Use new field. - (m4__push_symbol, file_clean): Update signature. - (composite_read): Bump refcount when done with reference. - (composite_clean): New function. - (pop_input): Adjust caller. - * m4/debug.c (m4_debug_message): Make assertion match comment. - * modules/gnu.c (builtin, indir): Adjust callers. - * tests/builtins.at (ifelse): New test. - (exp): Move and rename... - * tests/others.at (countdown): ...to this. - * doc/m4.texinfo (Improved foreach): Fix tracing usage in - example. - -2007-12-13 Eric Blake - - Yet more rewording. - * doc/m4.texinfo (Inhibiting Invocation): Missed one instance in - the previous patch. - - * THANKS: Update. - -2007-12-13 Paolo Bonzini (tiny change) - - * doc/m4.texinfo (Inhibiting Invocation): Fix quoting of a quoting - example. - Reported by Giovanni Toffetti. - -2007-12-11 Eric Blake - - Stage 7: use chained input support in input parser. - Allow the LIFO input engine to rescan a macro expansion composed - of smaller chunks of FIFO data, rather than the old approach of a - monolithic string. For now, all chunks are still copied. - Memory impact: slight penalty, due to FIFO chain overhead. - Speed impact: slight penalty, due to extra bookkeeping. - * m4/m4private.h (m4__push_symbol): New prototype. - (struct m4_symbol_chain): Add const-safety. - * m4/symtab.c (m4_symbol_value_print): Simplify. - (dump_symbol_CB): Update caller. - * m4/input.c (struct m4_input_block): Alter u_c member, first - introduced 2006-10-25, but unused until now. - (composite_peek, composite_read, composite_unget) - (composite_print, init_builtin_token): Rewrite accordingly. - (m4_push_wrapup): No longer need trailing NUL. - (m4__push_symbol, make_text_link): New functions. - (m4_push_string_finish): Use them. - * m4/macro.c (m4_push_arg, m4_push_args): Likewise. - (expand_macro): Simplify logic of nesting_limit. - * src/main.c (main): Likewise. - * doc/m4.texinfo (Dumpdef): Augment test. - -2007-12-08 Eric Blake - - Stage 6: convert builtins to push arg at a time. - Add new methods to factor all builtins whose expansion includes an - argument, making back-reference creation easier in future patches. - Factor out length-limited printing to obstacks, and use -1 rather - than 0 for unlimited length. - Memory impact: none. - Speed impact: slight improvement, due to better code sharing. - * m4/m4module.h (m4_shipout_text): Rename... - (m4_divert_text): ...to this, to avoid confusion with m4_shipout_* - that does not worry about sync lines. - (m4_shipout_string_trunc): New prototype. - * m4/output.c (m4_shipout_text): Rename... - (m4_divert_text): ...to this. - (m4_shipout_string): Move guts... - (m4_shipout_string_trunc): ...to this new function. - * m4/macro.c (m4_push_arg, m4_push_args): New functions. - (expand_token, process_macro): Update callers. - * m4/input.c (string_print): Likewise. - * modules/m4.c (ifdef, ifelse, shift, substr, translit, divert): - Likewise. - * modules/gnu.c (patsubst): Likewise. - (debuglen): Use SIZE_MAX for unlimited debug length. - * src/main.c (main): Likewise. - * m4/m4.c (m4_create): Default max_debug_length to SIZE_MAX, not - zero. - -2007-12-07 Eric Blake - - Minor security fix: Quote output of mkstemp. - * modules/m4.c (m4_make_temp): Produce quoted output. - * doc/m4.texinfo (Mkstemp, Mkdtemp): Update the documentation and - tests. - - Stage 5: add notion of quote age. - Cache the quoting rules that were in effect when a string was - parsed, to avoid reparsing that string if no changequote or other - quote age change took place in the meantime. A quote_age of 0 is - always safe, but does not benefit from caching. - Memory impact: slight improvement, due to smaller struct in input - engine. - Speed impact: slight penalty, due to more bookkeeping. - * m4/m4module.h (m4_get_symbol_value_quote_age): New prototype. - (m4_set_symbol_value_text): Adjust prototype. - (m4_has_syntax): Factor out the unsigned char cast. - * m4/m4private.h (struct m4_syntax_table): Add syntax_age and - quote_age members. - (m4__quote_age, m4__safe_quotes): New accessor macros, no need for - functions at this point. - (struct m4_symbol_value, struct m4_macro_args): Add quote_age - member. - (m4_set_symbol_value_text): Adjust fast accessor. - (m4_get_symbol_value_quote_age): New fast accessor. - * m4/symtab.c (m4_set_symbol_value_text): Add parameter. - (m4_get_symbol_value_quote_age): New function. - (m4_symbol_value_copy): Adjust callers. - * m4/macro.c (expand_token): Add parameter, and track quote age. - (expand_argument, collect_arguments): Track quote age. - (m4_macro_expand_input, process_macro, m4_make_argv_ref) - (m4_macro_expand_input): Update callers. - (m4_arg_text, m4_arg_len, m4_arg_func): Abort on type mismatch. - * m4/input.c: Comment cleanups. - (struct m4_input_block): Reduce size. - (m4__next_token): Report quote age. - (m4_push_builtin, init_builtin_token): Update callers. - * m4/utility.c (skip_space): Adjust callers. - * m4/module.c (install_macro_table): Likewise. - * m4/syntax.c (m4_set_syntax): Initialize and update quote age. - (m4_set_quotes, m4_set_comment): Detect no-op changes, and update - quote age. - (set_quote_age): New helper function. - (check_is_single_quotes, check_is_single_comments): Adjust - callers. - * src/freeze.c (reload_frozen_state): Likewise. - * src/main.c (main): Likewise. - * modules/m4.c (define, pushdef): No need to set macro text. - * tests/builtins.at (changequote, defn): New tests. - * examples/wrapfifo.m4: New file. - * examples/wraplifo.m4: New file. - * Makefile.am (dist_pkgdata_DATA): Distribute new examples. - -2007-12-04 Eric Blake - - Fix builds with OpenBSD make. - * Makefile.am (HELP2MAN): New macro. - (dist_man_MANS, doc/m4.1): Fix rules for building m4.1 into - srcdir. - * README: Update copyright. - * HACKING: Mention help2man and makeinfo dependencies. - -2007-11-29 Eric Blake - - Stage 4: route indir, builtin through ref; make argv opaque. - Finish making struct opaque to all but the input engine, by - reworking obstack usage in expand_macro to better support creation - of a $@ reference. Canonicalize the empty argument, to allow - pointer comparison optimizations. - Memory impact: slight penalty, due to larger struct. - Speed impact: slight improvement, due to fewer function calls. - * m4/system_.h (obstack_regrow): Fix precedence. - * m4/m4module.h (m4_arg_equal, m4_arg_empty, m4_make_argv_ref): - New prototypes. - (struct m4_macro_args): Move... - * m4/m4private.h (struct m4_macro_args): ...here, making it opaque - to modules. Add has_ref member. - (bool_bitfield): New helper typedef. - (struct m4_symbol_chain): Add flatten and len members. - * m4/macro.c (empty_symbol): New placeholder, for optimizing - comparison with empty string. - (m4_macro_expand_input): Initialize it. - (collect_arguments): Alter signature, and populate new fields. - (trace_pre, trace_post): Remove redundant parameter. - (expand_macro): Alter handling of obstacks. - (m4_arg_symbol): Account for wrapped argv. - (m4_arg_equal, m4_arg_empty, m4_make_argv_ref): New methods. - (m4_arg_text, m4_arg_len, m4_arg_func): Use new methods. - * modules/m4.c (ifelse, syscmd): Likewise. - * modules/evalparse.c (m4_evaluate): Likewise. - (undefine, popdef, m4_dump_symbols): Optimize. - * modules/gnu.c (builtin, indir, esyscmd, debugfile): Use new - methods. - (changesyntax, regexp): Optimize. - * m4/output.c (diversion_storage): Use typedef. - - Stage 3b: cache length, rather than computing it, in modules. - Use cached token length in builtins and output engine. - Memory impact: none. - Speed impact: noticeable improvement, due to fewer function calls. - * m4/hash.c (m4_hash_remove): Avoid double free on remove - failure. - * m4/output.c (m4_shipout_string): Change semantics of len param. - (m4_shipout_int): Use cached length. - * m4/input.c (m4_push_string_finish): Likewise. - * modules/m4.h (m4_make_temp_func): Add parameter. - * m4/macro.c (expand_token, m4_arg_len): Use cached length. - (collect_arguments, expand_macro): Alter signature. - (trace_format): Don't use out-of-scope buffer. - (process_macro): All callers changed. - * m4/utility.c (m4_dump_args): Likewise. - * m4/symtab.c (m4_symbol_value_print): Likewise. - * modules/gnu.c (__file__, __program__, builtin, indir) - (m4symbols, mkdtemp, regexp_compile, regexp_substitute, - renamesyms, patsubst, regexp, regexp_compile): Likewise. - * modules/load.c (m4modules): Likewise. - * modules/m4.c (defn, m4wrap, maketemp, m4_make_temp) - (numb_obstack, ifdef, ifelse, divert, len, substr): Likewise. - * modules/perl.c (perleval): Likewise. - * modules/stdlib.c (getcwd, getenv, getlogin, getpwnam, getpwuid) - (hostname, uname, setenv): Likewise. - * modules/mpeval.c (numb_obstack): Likewise. - * src/freeze.c (dump_symbol_CB): Likewise. - * doc/m4.texinfo (Renamesyms, Dumpdef, Changesyntax): Adjust test. - * tests/builtins.at (mkstemp): Likewise. - * tests/others.at (iso8859): XFAIL this test, now that - length-based handling allows NUL through part but not all of M4. - -2007-11-28 Eric Blake - - Stage 3a: cache length, rather than computing it, in libm4. - Cache the length of a token in the input engine and symbol table, - to avoid repeating lots of strlen calls. Additionally, by using - obstack length rather than strlen, the input engine can now - support embedded NUL. - Memory impact: slight penalty, due to larger struct. - Speed impact: slight improvement, due to fewer function calls. - * m4/m4module.h (struct m4_macro_args): Cache length. - (m4_get_symbol_len, m4_get_symbol_value_len): New accessors. - (m4_set_symbol_value_text): Change signature. - * m4/m4private.h (struct m4_symbol_value): Store string length. - (m4_get_symbol_value_text, m4_get_symbol_value_placeholder) - (m4_set_symbol_value_placeholder): Update accordingly. - (m4_set_symbol_value_text): Change signature. - (m4_get_symbol_value_len): New accessor. - * m4/input.c (struct m4_input_block, string_peek, string_read) - (string_unget, string_print, m4_push_string_finish) - (m4_push_wrapup): Track length of string input. - (m4__next_token): Adjust all users of symbol text to track length, - too. - * m4/macro.c (expand_argument, collect_arguments): Likewise. - * m4/module.c (install_macro_table): Likewise. - * modules/gnu.c (builtin, indir): Likewise. - * modules/m4.c (define, pushdef): Likewise. - * src/main.c (main): Likewise. - * src/freeze.c (reload_frozen_state): Likewise. - * m4/symtab.c (m4_symbol_value_copy): Likewise. - (m4_get_symbol_value_len): New function. - (m4_get_symbol_value_text, m4_get_symbol_value_placeholder) - (m4_set_symbol_value_text, m4_set_symbol_value_placeholder): - Adjust implementation. - -2007-11-27 Eric Blake - - Stage 2: use accessors, not direct reference, into argv. - Outside of macro.c, use accessor methods rather than direct access - into the argv struct. - Memory impact: none. - Speed impact: slight penalty, due to increased function calls. - * m4/m4private.h (m4_arg_argc): New fast accessor. - * m4/m4module.h (m4_arg_argc, m4_arg_symbol, m4_is_arg_text) - (m4_is_arg_func, m4_arg_text, m4_arg_len, m4_arg_func): New - prototypes. - (m4_builtin_func, M4BUILTIN, M4BUILTIN_HANDLER, m4_dump_args) - (m4_macro_call): Make argc unsigned. - (M4ARG): Use new accessors. - * modules/m4.c (define, pushdef): Likewise. - (undefine, popdef, ifelse, m4_dump_symbols, defn, undivert) - (traceon, traceoff): Make argc unsigned. - * modules/m4.h (m4_dump_symbols_func): Likewise. - * modules/evalparse.c (m4_evaluate): Likewise. - * modules/gnu.c (builtin, indir): Use new accessors. - (changesyntax): Make argc unsigned. - * modules/perl.c (perleval): Likewise. - * m4/utility.c (m4_dump_args): Use new accessors. - * m4/macro.c (trace_pre): Likewise. - (m4_arg_symbol, m4_arg_argc, m4_is_arg_text, m4_is_arg_func) - (m4_arg_text, m4_arg_len, m4_arg_func): New functions. - (expand_macro, trace_pre, trace_post, m4_macro_call): Update argc - usage. - -2007-11-24 Eric Blake - - Stage 1: convert m4_symbol_value** into new object. - Pass a variable-size wrapper structure instead of an array to - builtins, so that subsequent optimizations in the structure need - not impact every builtin client. - Memory impact: slight penalty, since struct is larger than array. - Speed impact: slight penalty, due to increased bookkeeping. - * ltdl/m4/gnulib-cache.m4: Import flexmember module. - * m4/m4module.h (m4_macro_args): New type, will be opaque to - modules later. - (m4_builtin_func, M4BUILTIN, M4BUILTIN_HANDLER, m4_dump_args) - (m4_macro_call): Alter signature to use m4_macro_args object. - (M4ARG): Redefine to access new struct. - * m4/m4private.h (M4_SYMBOL_COMP): New enumerator. - (struct m4_symbol_chain): New type. - (struct m4_symbol_value): Add chain alternative. - * m4/macro.c (collect_arguments): Build new struct. - (expand_macro, m4_macro_call, process_macro, trace_pre) - (trace_post): Adjust implementation to use it. - * m4/utility.c (m4_dump_args): Likewise. - * modules/gnu.c (builtin, indir): Likewise. - * modules/format.c (format): Likewise. - * modules/m4.h (m4_dump_symbols_func): Likewise. - * modules/m4.c (m4_dump_symbols, define, pushdef, defn, ifelse) - (shift, include, errprint, m4wrap): Likewise. - * modules/evalparse.c (m4_evaluate): Likewise. - - Pass only macro name to utility functions. - * m4/m4module.h (m4_bad_argc, m4_numeric_arg): Adjust signature. - * m4/utility.c (m4_bad_argc, m4_numeric_arg): Adjust - implementation. - * m4/macro.c (m4_macro_call): Adjust callers. - * modules/gnu.c (builtin, debuglen): Likewise. - * modules/m4.c (ifelse, incr, decr, divert, undivert, m4exit) - (substr): Likewise. - * modules/evalparse.c (m4_evaluate): Likewise. - * modules/stdlib.c (setenv, getpwuid, srand): Likewise. - * modules/time.c (ctime, gmtime, localtime, mktime, strftime): - Likewise. - -2007-11-23 Eric Blake - - Add macro name to debugfile messages. - * m4/m4module.h (m4_debug_set_output): Add parameter. - * m4/debug.c (m4_debug_set_output, set_debug_file): Pass macro - name through. - * modules/gnu.c (debugfile): Adjust caller. - * modules/m4.c (m4exit): Likewise. - * src/main.c (main): Likewise. - - Factor out handling of macro name in error messages. - * m4/m4module.h (m4_error, m4_error_at_line, m4_warn) - (m4_warn_at_line): Add new parameter. - * m4/utility.c (m4_verror_at_line): New helper method. - (m4_error, m4_error_at_line, m4_warn, m4_warn_at_line): Add new - parameter. - (m4_bad_argc, m4_numeric_arg, m4_parse_truth_arg): All callers - changed. - * m4/debug.c: Likewise. - * m4/input.c: Likewise. - * m4/macro.c: Likewise. - * m4/module.c: Likewise. - * m4/output.c: Likewise. - * m4/path.c: Likewise. - * modules/evalparse.c: Likewise. - * modules/format.c: Likewise. - * modules/gnu.c: Likewise. - * modules/load.c: Likewise. - * modules/m4.c: Likewise. - * modules/mpeval.c: Likewise. - * src/freeze.c: Likewise. - * src/main.c: Likewise. - -2007-11-14 Eric Blake - - Handle some defn corner cases differently. - * doc/m4.texinfo (Defn): Update documentation; although this still - doesn't match the branch, since it may be changed before 2.0. - * m4/macro.c (expand_argument): Consistently ignore builtins in - concatenation contexts. - * m4/m4private.h (m4__symbol_type): Fix C89 compliance bug. - -2007-11-13 Eric Blake - - Note: Patches titled Stage 0 through N form a series of patches - which decreases the algorithmic complexity of tail recursion in - macro expansions from O(n^2) to O(n) in both time and memory, then - performs cleanups, such as handling of embedded NUL, made easier - by the code refactoring. - - Stage 0: Fix memory leak in tail recursion. - Free expansion text in the input engine as soon as it is parsed, - rather than when the recursive expansion completes. - Memory impact: noticeable improvement, due to reduction from - O(n^2) to O(n) on recursion. - Speed impact: minor improvement, due to better memory usage. - * m4/input.c (pop_input): Add flag parameter and return type. - (next_char): Adjust caller. - (m4_push_string_init): Let go of memory earlier. - -2007-11-07 Eric Blake - - * tests/macros.at (Rescanning macros): Test more corner cases. - -2007-11-06 Eric Blake - - * build-aux/mkstamp: Rename from ltdl/config/mkstamp. - - * Makefile.am (tests/package.m4): Work around bash bug. - Reported by Ralf Wildenhues. - -2007-11-05 Eric Blake - - For consistency with other GNU projects, use build-aux directory. - * configure.ac (AC_CONFIG_AUX_DIR): Change ltdl/config to - build-aux. - * bootstrap (config_aux_dir): Likewise. - * Makefile.am (config_aux_dir): Likewise. - * ltdl/m4/gnulib-cache.m4: Use --aux-dir option. - -2007-11-02 Eric Blake - - Update some documentation about version control. - * NEWS: M4 is now stored in git. - * HACKING: Likewise. - * README: Likewise. - * bootstrap: Likewise. - * commit: Delete, now that CVS commits are no longer necessary. - * ltdl/config/mailnotify: No longer necessary; git's patch - generation and mail capability is more powerful. - - Update to recent gnulib changes. - * ltdl/m4/gnulib-cache.m4: Replace fprintf-posix, vasprintf-posix, - xprintf, and xvasprintf with xprintf-posix and xvasprintf-posix. - -2007-11-01 Eric Blake - - Improve error message when early end of file occurs. - * doc/m4.texinfo (Macro Arguments, Changequote, Changecom) - (M4wrap): Adjust to new messages. - (Improved capitalize): Enhance test. - * m4/m4private.h (m4__next_token): Adjust prototype. - * m4/input.c (m4__next_token): Add new parameter, and improve - error message. - * m4/macro.c (m4_macro_expand_input, collect_arguments): Adjust - callers. - (expand_argument): Likewise, and add parameter. - -2007-10-31 Eric Blake - - Test more corner cases. - * tests/macros.at (Rescanning macros): Beef up test. - * doc/m4.texinfo (Changecom): Beef up test. - (Improved foreach): Document alternate foreachq style. - * examples/foreachq3.m4: New file. - * examples/loop.m4: New file. - * Makefile.am (dist_pkgdata_DATA): Distribute them. - -2007-10-28 Eric Blake - - More test coverage for autoconf usage patterns. - * doc/m4.texinfo (Shift): Document cond macro, and add new test. - * tests/macros.at (Rescanning macros): New test. - * tests/builtins.at (include): Augment test. - -2007-10-28 Ralf Wildenhues - - * Makefile.am: Adjust getopt handling to latest gnulib layout. - -2007-10-27 Eric Blake - - Document one use of changequote(`(',`)'). - * doc/m4.texinfo (Changequote): Add new test, based on recent - autoconf addition of m4_expand. - -2007-10-24 Ralf Wildenhues - - * Makefile.am (dist_pkgdata_DATA): Add examples/capitalize2.m4. - -2007-10-22 Eric Blake - - Never let printf failures go undetected. - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool --import - xprintf'. - * m4/system_.h: Include xprintf.h. - * m4/debug.c (m4_debug_message_prefix, m4_debug_message): Wrap all - use of printf, xprintf. - * m4/input.c [DEBUG_INPUT]: Likewise. - * m4/module.c [DEBUG_MODULES]: Likewise. - * m4/output.c (m4_shipout_text, m4_shipout_int) - (m4_freeze_diversions): Likewise. - * m4/path.c [DEBUG_INCL]: Likewise. - * m4/symtab.c [DEBUG_SYM]: Likewise. - * m4/syntax.c [DEBUG_SYNTAX]: Likewise. - * modules/modtest.c (export_test): Likewise. - * src/freeze.c (produce_resyntax_dump, produce_syntax_dump) - (produce_module_dump, dump_symbol_CB, produce_frozen_state): - Likewise. - * src/main.c (usage): Likewise. - * po/POTFILES.in: Adjust to new file. - * po/Makevars (XGETTEXT_OPTIONS): Likewise. - -2007-10-18 Eric Blake - - Fix 'm4 -F file -t undefined'. - * src/freeze.c (produce_symbol_dump): Skip trace placeholders. - * src/freeze.c (dump_symbol_CB): Also skip void symbols. - * tests/freeze.at (reloading unknown builtin): Test for this bug. - * m4/m4module.h (m4_symtab_apply): Add parameter. - * m4/symtab.c (m4_symtab_apply): Ignore trace placeholders when - requested. - (m4_symtab_delete, symtab_dump): Adjust callers. - * modules/m4.c (m4_dump_symbols): Likewise. - -2007-10-09 Eric Blake - - Fix regexp regression of 2007-09-29. - * modules/gnu.c (substitute): Allow NULL buf when no - subexpressions were present. - (regexp): Handle \ escapes even with empty regex. - * doc/m4.texinfo (Regexp, Patsubst): Catch this bug. - - Cache regex compilation for another autoconf speedup. - * modules/gnu.c (gnu_buf): Replace... - (REGEX_CACHE_SIZE, regex_cache): ...with new declarations. - (m4_pattern_buffer): Add fields. - (m4_regexp_compile): Rename... - (regexp_compile): ...to this, and drop no_sub parameter. - Implement caching. - (M4FINISH_HANDLER): Clean up entire cache. - (m4_regexp_search): Rename... - (regex_search): ...to this, adjust to new struct contents, and add - no_sub parameter. - (m4_regexp_substitute): Rename... - (regexp_substitute): ...to this. - (substitute, patsubst, regexp, renamesyms): Adjust callers. - -2007-10-02 Eric Blake - - Document quoting pitfalls in capitalize. - * doc/m4.texinfo (Patsubst): Use the examples directory. Also - document shortfall. - (Improved capitalize): New node. - * examples/capitalize.m4: Update to match manual. - * examples/capitalize2.m4: New file. - -2007-10-01 Eric Blake - - Another Autoconf usage pattern optimization. - * modules/m4.c (m4_index): Optimize search for one byte. - * doc/m4.texinfo (Index macro, Regexp, Patsubst): Test the new - code paths. - -2007-09-29 Eric Blake - - Optimize for Autoconf usage pattern. - * modules/gnu.c (regexp, patsubst): Handle empty regex faster. - - * tests/testsuite.at (AT_CHECK_M4): Slight optimization. - -2007-09-24 Eric Blake - - Create .gitignore alongside .cvsignore. - * bootstrap (version control): Update to reflect git usage. - -2007-09-13 Eric Blake - - * AUTHORS: Fix typo. - -2007-09-12 Gary V. Vaughan - - Be consistent about using 'module' for m4_module types and - 'handle' for lt_dlhandle types: - - * m4/m4private.h (m4_symbol_value): Rename handle element to - method. Changed all references. - (VALUE_MODULE, SYMBOL_MODULE): Renamed from VALUE_HANDLE and - SYMBOL_HANDLE respectively. Changed all references. - * m4/m4module.h (M4INIT_HANDLER, M4FINISH_HANDLER): Ditto. - * m4/builtin.c (m4_builtin_find_by_name) - (m4_builtin_find_by_func): Use module as the parameter name for - pointers of type 'm4_module'. - * m4/module.c (module_remove, m4_get_module_name) - (install_builtin_table, install_macro_table) - (m4_module_make_resident, m4__module_next, m4_module_refcount): - Ditto. - * src/freeze.c (produce_module_dump): Ditto. - * m4/input.c (m4_input_block): Rename handle element to method. - Changed all references. - * m4/symtab.c (m4__symtab_remove_module_references): Ditto. - * modules/load.c: Use module as the variable name for pointers - of type 'm4_module'. - * modules/m4.c: Ditto. - * modules/perl.c: Ditto. - * modules/shadow.c: Ditto. - -2007-09-07 Eric Blake - - Add refcount builtin. - * modules/load.c (refcount): New builtin. - (m4modules): Use correct type. - * doc/m4.texinfo (Refcount): New section. - * m4/m4private.h (struct m4_module): Add refcount member. - (m4_module_refcount) [NDEBUG]: Add faster accessor macro. - * m4/module.c (m4_module_load): Add symbols to table on first - load by m4, regardless of other libltdl loads of same module. - (m4_module_refcount): Use new struct member, rather than relying - on libltdl count which might be inflated by unrelated loads. - (m4__module_interface): Optimize. - (m4__module_next, m4__module_find): Avoid assertions that could - trigger with unrelated libltdl loads. - (m4__module_open): Track m4 load count. - (m4__module_exit): Only unload what m4 loaded. - (module_remove): Track m4 unloads. - * NEWS: Document new builtin. - - More conversion to m4_module*. - * src/freeze.c (produce_module_dump, dump_symbol_CB) - (reload_frozen_state): Use correct type. - * m4/input.c (struct m4_input_block): Likewise. - * m4/symtab.c (dump_symbol_CB): Likewise. - - * AUTHORS: Simplify, to match libtool and autoconf layout. - * THANKS: Sync with branch. - -2007-09-06 Eric Blake - - Wrap lt_dlhandle in struct m4_module. - * m4/m4module.h (includes): No longer require clients to know - about lt_dlhandle. - (m4_module): New opaque declaration. - (m4_export): Delete unused type. - (M4INIT_HANDLER, M4FINISH_HANDLER, m4_module_init_func) - (m4_module_finish_func, m4_module_load, m4_get_module_name) - (m4_builtin_find_by_name, m4_builtin_find_by_func): Use new - wrapper. - (m4_module_makeresident, m4_module_refcount): New declarations. - * m4/m4private.h (includes): Move here. - (m4_module): New declaration. Simple for now, but intended for - growth. - (m4__module_open, m4__module_next, m4__module_find) - (m4__symtab_remove_module_references): Use new wrapper. - * m4/builtin.c (m4_builtin_find_by_name, m4_builtin_find_by_func): - Likewise. - * m4/module.c (m4_get_module_name, m4_module_import) - (m4_module_load): Likewise. - (install_builtin_table, install_macro_table): Likewise. Also, - change return type since these always returned NULL and no one - used the result. - (m4_module_makeresident, m4_module_refcount): New functions. - (m4_module_unload, m4__module_next, m4__module_find): Use new - wrapper. - (m4__module_open): Populate new wrapper, and associate it with the - lt_dlhandle. - (m4__module_exit): Use new wrapper. - (module_remove): Likewise. Reclaim storage on last use. - (module_close): Delete, and inline into module_remove. - * m4/symtab.c (m4__symtab_remove_module_references): Use new - wrapper. - * modules/load.c (load_init): Use new API. - * modules/m4.c (m4_export_table): Kill unused declaration. - (m4_init): Use new API. - * modules/shadow.c (shadow_init): Use new API. - * src/main.c (main): Adjust callers. - * src/freeze.c (reload_frozen_state): Likewise. - * tests/modules.at (unload load module): New test. - -2007-09-03 Gary V. Vaughan - - * bootstrap (ltdl/m4/.cvsignore): Add xstrtol module macros. - * src/m4/.cvsignore: Add xstrtol module sources. - -2007-09-03 Gary V. Vaughan - - Work around a bug in darwin's awk: - - * bootstrap (func_get_translations): Use $AWK instead of raw - `awk' so that the user can use an alternative implementation - if the first awk in PATH doesn't behave as expected. - (func_get_translations): The first awk script mangles the last - entry passed to it for at least the awk implementation shipped - with Darwin 8.10.1. Capture $3 into a variable too to work- - around that problem. - -2007-08-29 Gary V. Vaughan - - As gnulib xstrtol is only used by main, and unconditionally pulls - in a copy of getopt, undo bootstrap change from 2007-08-11 below, - and copy the xstrtol code into src/ so that main() can use it - without pushing the extra code into libm4: - - * bootstrap (src_modules): Add getopt and xstrtol modules. - * Makefile.am (src_m4_SOURCES): Add xstrtol sources. - * po/POTFILES.in: Move gnu/xstrtol-error.c to src/xstrtol-error.c. - -2007-08-11 Eric Blake - - Another upstream xstrtol change. - * po/POTFILES.in: Track changes in files containing messages. - * bootstrap (src_modules): getopt is now pulled into libgnu.a, no - need to grab it separately. - * src/main.c (OPT_STR, LONG_OPT_STR, short_opt_str, OPT_STR_INIT): - No longer needed. - (size_opt): Adjust to latest xstrtol interface. - -2007-08-10 Eric Blake - - Documentation improvements. - * doc/m4.texinfo (Defn): Resync with branch. - (Compatibility, Extensions): Sync with branch. - -2007-08-07 Eric Blake - - Adjust to gnulib xstrtol changes. - * src/main.c (size_opt): Adjust signature, so that error strings - are easier to translate. - (OPT_STR, LONG_OPT_STR, short_opt_str, OPT_STR_INIT): New macros - for tracking long options. - (main): Track which long option was used. - * tests/options.at (--debuglen, --nesting-limit): Adjust to change - in error message. - (deprecated options): Test that --arglength spelling shows up in - error message. - -2007-08-06 Eric Blake - - Normalize all GPL license notices. - * m4/COPYING.LIB: Delete - libm4 is not distributed under LGPLv2 - at this time. - * Makefile.am: Update license wording. - * bootstrap: Likewise. - * commit: Likewise. - * configure.ac: Likewise. - * ltdl/config/mailnotify: Likewise. - * ltdl/config/mkstamp: Likewise. - * ltdl/m4/debug.m4: Likewise. - * ltdl/m4/gmp.m4: Likewise. - * ltdl/m4/m4-error.m4: Likewise. - * ltdl/m4/m4-getopt.m4: Likewise. - * ltdl/m4/m4-gettext.m4: Likewise. - * ltdl/m4/m4-obstack.m4: Likewise. - * ltdl/m4/m4-regex.m4: Likewise. - * ltdl/m4/stackovf.m4: Likewise. - * m4/builtin.c: Likewise. - * m4/debug.c: Likewise. - * m4/hash.c: Likewise. - * m4/hash.h: Likewise. - * m4/input.c: Likewise. - * m4/m4.c: Likewise. - * m4/m4module.h: Likewise. - * m4/m4private.h: Likewise. - * m4/macro.c: Likewise. - * m4/module.c: Likewise. - * m4/output.c: Likewise. - * m4/path.c: Likewise. - * m4/resyntax.c: Likewise. - * m4/symtab.c: Likewise. - * m4/syntax.c: Likewise. - * m4/system_.h: Likewise. - * m4/utility.c: Likewise. - * modules/evalparse.c: Likewise. - * modules/format.c: Likewise. - * modules/gnu.c: Likewise. - * modules/import.c: Likewise. - * modules/load.c: Likewise. - * modules/m4.c: Likewise. - * modules/m4.h: Likewise. - * modules/modtest.c: Likewise. - * modules/mpeval.c: Likewise. - * modules/perl.c: Likewise. - * modules/shadow.c: Likewise. - * modules/stdlib.c: Likewise. - * modules/time.c: Likewise. - * modules/traditional.c: Likewise. - * po/Makevars: Likewise. - * src/freeze.c: Likewise. - * src/m4.h: Likewise. - * src/main.c: Likewise. - * src/stackovf.c: Likewise. - * tests/builtins.at: Likewise. - * tests/freeze.at: Likewise. - * tests/generate.awk: Likewise. - * tests/m4.in: Likewise. - * tests/macros.at: Likewise. - * tests/modules.at: Likewise. - * tests/options.at: Likewise. - * tests/others.at: Likewise. - * tests/stackovf.test: Likewise. - * tests/testsuite.at: Likewise. - -2007-07-22 Eric Blake - - Fix diversions on NetBSD, when fopen(name,"a+") seeks to end. - * m4/output.c (m4_tmpopen): Explicitly seek to beginning. - * tests/builtins.at (divert): Enhance test to cover this. - * THANKS: Update. - Reported by Thomas Klausner. - -2007-07-20 Eric Blake - - Fix 'make distcheck' issues. - * bootstrap: Add more files that might be more up-to-date in - gnulib. - * Makefile.am (EXTRA_DIST): No longer distribute removed diff. - * config/m4/gnulib-cache.m4: Update to latest gnulib. - -2007-07-16 Eric Blake - - * po/POTFILES.in: Track recent translation additions from gnulib - updates. - -2007-07-14 Eric Blake - - Reflect upstream license .texi changes. - * doc/m4.texinfo (Copying): Rename node... - (GNU General Public License): ...to this. - (GNU Free Documentation License): Adjust node location. - * local/doc/gpl-3.0.texi.diff: Remove file. - -2007-07-10 Eric Blake - - Upgrade to GPLv3, and document 1.4.10. - * bootstrap: Adjust to GPLv3. - (func_update): Port from branch. - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool - --local-dir=local --import gpl-3.0'. - * doc/m4.texinfo (History): Mention 1.4.11. - (Copying This Package): New appendix. - * NEWS: Document 1.4.10. - * local/doc/gpl-3.0.texi.diff: New file. - * Makefile.am: Update license. - (doc_m4_TEXINFOS, EXTRA_DIST): Distribute additions. - * commit: Update license. - * configure.ac: Likewise. - * ltdl/config/mailnotify: Likewise. - * ltdl/config/mkstamp: Likewise. - * ltdl/m4/debug.m4: Likewise. - * ltdl/m4/gmp.m4: Likewise. - * ltdl/m4/m4-error.m4: Likewise. - * ltdl/m4/m4-getopt.m4: Likewise. - * ltdl/m4/m4-gettext.m4: Likewise. - * ltdl/m4/m4-obstack.m4: Likewise. - * ltdl/m4/m4-regex.m4: Likewise. - * ltdl/m4/stackovf.m4: Likewise. - * m4/builtin.c: Likewise. - * m4/debug.c: Likewise. - * m4/hash.c: Likewise. - * m4/hash.h: Likewise. - * m4/input.c: Likewise. - * m4/m4.c: Likewise. - * m4/m4module.h: Likewise. - * m4/m4private.h: Likewise. - * m4/macro.c: Likewise. - * m4/module.c: Likewise. - * m4/output.c: Likewise. - * m4/path.c: Likewise. - * m4/resyntax.c: Likewise. - * m4/symtab.c: Likewise. - * m4/syntax.c: Likewise. - * m4/system_.h: Likewise. - * m4/utility.c: Likewise. - * modules/evalparse.c: Likewise. - * modules/format.c: Likewise. - * modules/gnu.c: Likewise. - * modules/import.c: Likewise. - * modules/load.c: Likewise. - * modules/m4.c: Likewise. - * modules/m4.h: Likewise. - * modules/modtest.c: Likewise. - * modules/mpeval.c: Likewise. - * modules/perl.c: Likewise. - * modules/shadow.c: Likewise. - * modules/stdlib.c: Likewise. - * modules/time.c: Likewise. - * modules/traditional.c: Likewise. - * po/Makevars: Likewise. - * src/freeze.c: Likewise. - * src/m4.h: Likewise. - * src/main.c: Likewise. - * src/stackovf.c: Likewise. - * tests/builtins.at: Likewise. - * tests/freeze.at: Likewise. - * tests/generate.awk: Likewise. - * tests/m4.in: Likewise. - * tests/macros.at: Likewise. - * tests/modules.at: Likewise. - * tests/options.at: Likewise. - * tests/others.at: Likewise. - * tests/stackovf.test: Likewise. - * tests/testsuite.at: Likewise. - -2007-07-09 Eric Blake - - * modules/format.c (format): Avoid undefined behavior with %c. - -2007-07-01 Gary V. Vaughan - - The translation project has moved. - * bootstrap (func_get_translations): Use the new translation - project url. - (TP_URL): Removed. - -2007-06-26 Karl Berry (tiny change) - - Match Free Software Directory categories. - * doc/m4.texinfo (dircategory): Update. - -2007-05-31 Eric Blake - - Add extension to divert builtin. - * modules/m4.c (builtin_divert): Immediately divert second - argument. - * m4/output.c (m4_output_text): Allow 0 length. Fixes regression - from two days ago. - (m4_shipout_text): Short-circuit on zero length. - * tests/freeze.at (loading format 2): Expand test to catch - regression. Also check out-of-range version. - * tests/builtins.at (divert): Expand test to check corner cases - of extension. - * doc/m4.texinfo (Divert): Document the extension. - * NEWS: Likewise. - Reported by Daniel Richard G. - -2007-05-30 Eric Blake - - Port format improvements from branch. - * doc/m4.texinfo (History): Mention upcoming 1.4.10 release. - (Format): Enhance section. - * modules/format.c (format): Accept %'hhd, and issue warnings on - unrecognized specifiers. - * modules/gnu.c (builtin_format): Adjust how format is called. - -2007-05-28 Eric Blake - - * tests/options.at (--syncoutput): Add xfailed test. - - Fix sync line interaction with multiline comments. - * doc/m4.texinfo (Preprocessor features): Improve documentation. - (Syncoutput): Improve testsuite. - (Incompatibilities): Add testcase, and document bug. - * src/freeze.c (reload_frozen_state): Don't interfere with - synclines when reloading state. - * m4/input.c (m4__next_token): Report line where multiline tokens - start. - * m4/m4private.h (m4__token_type): Add parameter. - * m4/m4module.h (m4_output_text): Export. - (m4_shipout_text): Add parameter. - * src/macro.c (m4_macro_expand_input, expand_token) - (expand_argument): Adjust callers so that line is passed from - input to output. - * m4/output.c (output_text): Rename... - (m4_output_text): ...to this, and export. - (m4_insert_file, insert_diversion_helper): Update callers. - (m4_shipout_text): Take new parameter for start line of token. - Output at most one syncline per token. - Reported by Sergey Poznyakoff. - - Fix large diversion corner cases. - * tests/freeze.at (large diversion): New test. - * m4/output.c (m4_tmpfile, m4_tmpopen): Simplify use of errno. - (make_room_for): Use NULL, not 0, for pointers. - (m4_freeze_diversions): Allow freezing large diversions. - (insert_diversion_helper): Avoid using rewind. - - Also run gnulib unit tests during make check. - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool - --tests-base=tests/gnu --with-tests'. - * configure.ac (AC_CONFIG_FILES): Build tests/gnu testdir. - * Makefile.am (SUBDIRS): Run gnulib tests before ours. - -2007-05-25 Eric Blake - - * m4/system_.h: Include , for intmax_t. - * THANKS: Update. - Reported by Daniel Richard G. - -2007-05-24 Eric Blake - - Provide consistent shift semantics regardless of hardware. - * modules/m4.c (numb_lshift, numb_rshift, numb_urshift): Mask - before shifting. - (number, unumber): Always use [u]intmax_t. - Reported by Gary V. Vaughan. - - Support POSIX flush semantics on all platforms. - * modules/m4.c (m4_sysval_flush): Rely on gnulib. - * ltdl/m4/gnulib-cache.m4: Fix typo in previous commit. - - Work around cygwin and mingw fseeko bugs. - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool --import - fseeko'. - * modules/m4.c (m4_sysval_flush): Prefer fseeko over fseek. - -2007-04-25 Eric Blake - - Test that regression in 1.4.9's eval doesn't recur. - * doc/m4.texinfo (Eval): Check negative division. - * THANKS: Update. - -2007-04-12 Eric Blake - - Allow for running test in sticky or setgid directory. - * tests/builtins.at (mkdtemp): Adjust test. - - Don't test for broken sed too soon. - * tests/others.at (stdin seekable): Rearrange subtests. - - Work around 'stdin seekable' shortcoming on glibc. - * ltdl/m4/gnulib-cache.m4: Use closein instead of closeout. - * tests/others.at (stdin closed): Adjust to new output. - * src/main.c (process_file): No need to return anything. - (main): Use close_stdin instead of close_stdout. - Reported by Ralf Wildenhues. - - Enable autobuild usage. - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool --import - autobuild'. - * configure.ac (AB_INIT): Output autobuild information. - -2007-04-11 Eric Blake - - Address testsuite shortcoming in 'stdout full' on glibc. - * tests/others.at (stdout full): Adjust expected output when more - than 1k text is printed to /dev/full. - Reported by Ralf Wildenhues. - -2007-04-10 Eric Blake - - * tests/macros.at (Arity and defn): Fix quoting. - -2007-04-09 Eric Blake - - Address failure of 'seekable stdin' on Mac OS X. - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool --import - fflush'. - -2007-04-07 Eric Blake - - Include first in all C files, and not in headers. - Fixes regression for --disable-assert builds from 2007-04-02. - * src/m4.h (includes): Don't include config.h here. - * m4/m4private.h (includes): Likewise. - * m4/builtin.c: Include config.h before anything else. - * m4/debug.c: Likewise. - * m4/hash.c: Likewise. - * m4/input.c: Likewise. - * m4/m4.c: Likewise. - * m4/macro.c: Likewise. - * m4/module.c: Likewise. - * m4/symtab.c: Likewise. - * m4/syntax.c: Likewise. - * m4/utility.c: Likewise. - * src/freeze.c: Likewise. - * src/stackovf.c: Likewise. - -2007-04-03 Eric Blake - - * modules/m4.c (numb_ratio, numb_divide, numb_modulo): Avoid - SIGFPE on x86 architectures. - Reported by Ralf Wildenhues. - -2007-04-02 Eric Blake - - Fix warnings from last commit. - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool --import - fprintf-posix sprintf-posix'. - * m4/macro.c (expand_macro, trace_format): Use correct specifier - for size_t. - (process_macro): Avoid negative array index. - * src/freeze.c (produce_resyntax_dump, produce_module_dump) - (dump_symbol_CB, produce_frozen_state): Use correct specifier for - size_t. - -2007-04-02 Gary V. Vaughan - - Get rid of the last 'differs in signedness' compiler warnings: - - * m4/macro.c (process_macro): m4_get_symbol_value_text() returns - a regular 'char *', so variables to store the return address, - and iterate through it should be regular 'char *' too. - * m4/input.c (m4_input_block): The start and current members of - the string part of this union store regular 'char *' types, so - they should be regular 'char *' types too. - -2007-04-02 Gary V. Vaughan - - M4 was designed to have a small number of header files defining - the interfaces to several source files each. Keeping this in - mind allows us to tidy things up considerably. Having done this, - it becomes clear that some of the installed headers reference - other headers which are not installed (but that's another patch): - - * m4/m4private.h (stdio--.h, stdlib--.h, unistd--.h): Moved from - here... - * m4/system_.h (gnu/stdio--.h, gnu/stdlib--.h, gnu/unistd--.h): - ...to here, so client modules can benefit too. - (assert.h, errno.h, limits.h, sys/stat.h): Include one here at the - lowest level to save doing it multiple times elsewhere. - * m4/debug.c (stdio.h): Removed. The portable - is already included via m4private.h. - * modules/time.c (stdio.h): Ditto. - * modules/gnu.c (stdlib.h): Ditto resp . - * modules/stdlib.c (stdlib.h, unistd.h): Ditto resp - and , - * m4/m4private.h (m4module.h): Use angle brackets for an installed - file. - * m4/hash.h (system.h): Ditto. - * modules/gnu.c (progname.h): Removed. - * src/freeze.c (m4/system.h, m4private.h): Already included vi m4.h. - * m4/m4private.h (assert.h, errno.h): Already included via - m4/m4module.h. - * m4/input.c (ctype.h): Ditto. - * m4/module.c (ltdl.h): Ditto. - * m4/output.c (errno.h, limits.h, stdio.h, sys/types.h, sys/stat.h) - (unistd.h): Ditto. - * m4/path.c (config.h, stdlib.h): Ditto. - * m4/utility.c (config.h): Ditto. - * modules/evalparse.c (assert.h, ctype.h): Ditto. - * modules/gnu.c (assert.h, ctype.h, errno.h): Ditto. - * modules/import.c (assert.h): Ditto. - * modules/m4.c (assert.h, errno.h): Ditto. - * modules/modtest.c (assert.h): Ditto. - * modules/stdlib.c (sys/types.h): DittAo. - * src/m4.h (ctype.h, errno.h, string.h, sys/types.h, ltdl.h): - Ditto. - * src/stackovf.c (assert.h): Ditto. - * modules/gnu.c (m4/m4module.h, m4private.h): Build using the faster - private interfaces when NDEBUG is defined. - * modules/import.c (m4/m4module.h, m4private.h): Ditto. - * modules/load.c (m4/m4module.h, m4private.h): Ditto. - * modules/m4.c (m4/m4module.h, m4private.h): Ditto. - * modules/modtest.c (m4/m4module.h, m4private.h): Ditto. - * modules/mpeval.c (m4/m4module.h, m4private.h): Ditto. - * modules/perl.c (m4/m4module.h, m4private.h): Ditto. - * modules/shadow.c (m4/m4module.h, m4private.h): Ditto. - * modules/time.c (m4/m4module.h, m4private.h): Ditto. - * modules/traditional.c (m4/m4module.h, m4private.h): Ditto. - * src/m4.h (locale.h): Moved from here... - * src/main.h: ...to here. - (m4private.h): Already included via m4.h. - * src/stackovf.c (m4private.h): Ditto. - -2007-03-28 Gary V. Vaughan - - * Makefile.am (stamp-vcl): Removed. - (CONFIG_STATUS_DEPENDENCIES): Depend directly on ChangeLog. - -2007-03-28 Eric Blake - - * src/main.c (usage): Improve note to TRANSLATORS. - * m4/system_.h (EXIT_FAILURE): Reflect gnulib changes. - - * tests/builtins.at (__m4_version__): Fix bug when TIMESTAMP is - empty. - -2007-03-24 Eric Blake - - * m4/output.c (m4_output_init): Update to latest gnulib. - * bootstrap (ltdl/m4/.cvsignore): No longer track generated - .cvsignore in CVS. - * NEWS: Reflect release of 1.4.9. - * THANKS: Update. - -2007-03-07 Eric Blake - - * AUTHORS: Update - - Exercise gnulib's new POSIX *printf modules. - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool --import - vasprintf-posix'. - * modules/format.c (format): Support %a and %A. - * doc/m4.texinfo (Format): Test this addition. - * NEWS: Document this addition. - -2007-03-03 Eric Blake - - * m4/input.c (m4__next_token): Fix synclines when in batch mode. - * doc/m4.texinfo (M4exit): Synch another section. - (Syncoutput): Make similar to other sections. - -2007-03-01 Eric Blake - - * doc/m4.texinfo: Improve the indices. - (Concept index): Rearrange to be last. - (Sysval): Merge from branch. - - * doc/m4.texinfo (Syscmd, Esyscmd): Merge more doc sections. - -2007-02-28 Eric Blake - - POSIX XCU ERN 137 was approved. - * modules/mpeval.c (numb_extension): Delete. - * modules/m4.c (numb_extension): Likewise. - * modules/evalparse.c (comma_term, condition_term): Always - implement ?: and , operators. - * m4/symtab.c: Update comment to match reality. - * src/freeze.c (produce_frozen_state, reload_frozen_state): Avoid - dereferencing context directly when accessor exists. - * src/main.c (usage): Prefer GNU_M4 over EMACS. - (struct macro_definition): Rename... - (struct deferred): ...to match usage. All uses changed. - * doc/m4.texinfo (Eval): Document this change. - (Operation modes, Changeresyntax): Fix wording to prefer GNU_M4 - over emacs. - (Preprocessor features, Changesyntax): Fix inaccuracies. - * NEWS: Import branch NEWS items for 1.4.x series. Document - change in eval. - - POSIX XCU ERN 118 was approved. - * modules/m4.c (define): Kill posixly_correct distinction in - define behavior, since POSIX says GNU behavior complies. - * tests/builtins.at (define): Restore original semantics. - * doc/m4.texinfo (Pushdef): Document portability issues with - define. - (Incompatibilities): Clean up wording of what POSIX requires. - * NEWS: Document this. - -2007-02-26 Eric Blake - - Re-enable clean bootstrap on cygwin. - * Makefile.am (AM_LDFLAGS): For now, export all symbols from - modules, since otherwise we run afoul of current libtool - limitations on cygwin and mingw. - -2007-02-25 M. Levinson (tiny change) - - * src/freeze.c (reload_frozen_state): Avoid dereferencing freed - memory. Fixes regression introduced 2007-01-20. - -2007-02-25 Eric Blake - - * tests/freeze.at (loading format 2): Augment test to catch - regression introduced on 2007-01-20. - * THANKS: Update. - Reported by M. Levinson. - - * m4/system_.h (includes, EXIT_SUCCESS, EXIT_FAILURE): Adjust to - latest gnulib. - -2007-02-05 Eric Blake - - * tests/options.at (--fatal-warnings): New test. - * tests/others.at (stdin seekable): Exit on error. - * m4/m4private.h (M4_OPT_WARN_EXIT_BIT): New bit. - (m4_get_warnings_exit_opt): Access it. - * m4/m4module.h (m4_context_opt_bit_table): Access it. - * m4/utility.c (m4_error, m4_error_at_line): Only force an exit - on -EE. - (m4_warn, m4_warn_at_line): Change exit status on -E, and force - exit on -EE. - * src/m4.c (usage): Document new -E behavior. - (main): Make -E an additive option. - * doc/m4.texinfo (Operation modes): Document the change. - Reported by Ralf Wildenhues. - - * tests/others.at (stdin seekable): Fix bug in test. - * ltdl/m4/gnulib-cache.m4: Gnulib module strstr no longer exists. - - * m4/input.c (struct m4_input_block): Remove unused field traced. - -2007-02-03 Eric Blake - and Bruno Haible (tiny change) - - * doc/m4.texinfo (Input processing, Quoting Arguments): Beef up - the examples. - Reported by Bruno Haible. - -2007-01-31 Eric Blake - - * m4/resyntax.c (m4_regexp_syntax_encode): Detect allocation - failure. - -2007-01-26 Eric Blake - - * m4/symtab.c (includes): Adjust to latest gnulib. - * modules/m4.c (includes): Likewise. - -2007-01-23 Eric Blake - - * m4/m4module.h (M4_SYNTAX_ASSIGN): Delete this unused - extension to make enough room. - (M4_SYNTAX_IGNORE): Change value to zero, since the (commented) - code in input.c special cases this category. - (M4_SYNTAX_LBRACE, M4_SYNTAX_RBRACE): New values in preparation - for define(eleventh,${11}) extension. - * m4/syntax.c: Update comments accordingly. - (m4_syntax_create, m4_syntax_code): Handle { and }. - * m4/input.c (m4__next_token): Likewise. - * src/freeze.c (produce_frozen_state): Support new categories. - (reload_frozen_state): When loading version 1, disable syntax - features not present in 1.4.x. - * tests/freeze.at: Sort and rename existing tests. - (loading format 1): Ensure we don't break v1 frozen files that - used raw ${. - (loading format 2, reloading changecom, reloading changesyntax): - New tests. - * doc/m4.texinfo (Changesyntax, Frozen file format 1): Document - the new syntax categories. - (Arguments): Update the FIXME comment. - (M4wrap): Merge examples from branch, before worrying about fixing - m4wrap to obey POSIX. - (Using frozen files): Start merging from branch. - * NEWS: Update. - -2007-01-20 Eric Blake - - * src/freeze.c (produce_char_dump): Delete. Replace with... - (produce_mem_dump): ...this new function, to encode more strings. - Also make the coding easier to read and slightly more compact. - (produce_syntax_dump): Only dump non-default syntax codes. - (produce_module_dump, dump_symbol_CB, produce_frozen_state): - Encode non-ASCII characters in user-supplied strings. - (GET_STRING): Accept escape sequences in version 2. - * NEWS: Document this change. - * TODO: Update. - -2007-01-16 Eric Blake - - Port patch from branch for stack overflow detection on BSD/OS. - * ltdl/m4/stackovf.m4 (M4_SYS_STACKOVF): Check for stack_t.ss_sp. - * src/stackovf.c (setup_stackovf_trap) [HAVE_SIGALTSTACK && - ! HAVE_STACK_T_SS_SP]: Use this check. - Reported by Chris McGuire. - -2007-01-15 Eric Blake - - * tests/builtins.at (__m4_version__): New test. - * modules/traditional.c (m4_macro_table): Provide windows and os2 - macros, as appropriate. Add __traditional__ macro. - * modules/mpeval.c (m4_macro_table): Name the macro __mpeval__, - not __gmp__, to match module name. - * modules/load.c (m4_macro_table): Name the macro __load__, not - __modules__, to match module name. - * doc/m4.texinfo (History, Shell commands, Platform macros): Merge - from the branch. - (Standard Modules): Improve wording. - (Incompatibilities): Move platform macros into their own node. - (Load, Unload): Use actual examples. - * NEWS: Document this change. - * THANKS: Update. - -2007-01-13 Eric Blake - - * doc/m4.texinfo (Mpeval): Add tests. - * tests/testsuite.at (AT_CHECK_GMP): New filter, factored from... - * tests/builtins.at (gmp): ...here. Rename test to... - (mpeval): ...this. - * tests/generate.awk (new_test): Filter out mpeval tests when gmp - is not available. - * m4/m4module.h (m4_get_no_gnu_extensions_opt): Merge - no_gnu_extensions with posixly_correct_opt, since they were set in - sync. - * m4/m4private.h (struct m4): Remove no_gnu_extensions. - * src/main.c (main): Update caller. - * src/freeze.c (reload_frozen_state): Likewise. - * modules/m4.c (m4wrap): Likewise. - -2007-01-12 Eric Blake - - * m4/syntax.c (m4_set_comment): XCU ERN 131 was approved by - POSIX, so update the comment. - * doc/m4.texinfo (Inhibiting Invocation): XCU ERN 130 was - approved by POSIX, so we can always have blind macros, even when - POSIXLY_CORRECT. - (Ifelse): Mention the term `blind builtin'. - -2007-01-08 Ralf Wildenhues - - * doc/m4.texinfo: Fix a couple of typos. - -2007-01-08 Eric Blake - - * ltdl/m4/gnulib-cache.m4: Update for new year. - * ltdl/m4/gmp.m4 (_M4_LIB_GMP): Cover all error cases. - Reported by Ralf Wildenhues. - -2007-01-06 Eric Blake - - * m4/m4private.h (to_uchar): Move... - * m4/m4module.h: here, so modules can use it. - * src/main.c (usage, long_options): Support --posix as a synonym - for --traditional. - * modules/m4.c (numb_invert): Detect unsupported x**-y. - (numb_incr, numb_urshift, numb_extension): New macros. - (numb_obstack): Port patch from branch to support radix 1 output. - * modules/mpeval.c (numb_obstack): Use \ for ratios. - (numb_incr, numb_urshift, numb_extension): New macros. - (mpq2mpz): Warn rather than error. - * modules/evalparse.c (URSHIFT, NEGATIVE_EXPONENT): New - enumerators. - (eval_error): Rearrange, so that all ignorable errors are less - than SYNTAX_ERROR. - (eval_text, last_text): Obey C++ type safety rules. - (numb_pow): Change return type. - (exp_term): Adjust caller. - (m4_evaluate): Fail on bad exponent. - (logical_or_term, logical_and_term): Ignore failed ** in short - circuit. - (eval_lex): Fix typos when detecting <<= and >>=. Use \ instead - of : for ratio. Support >>>, ,, and ?:. Port patch from branch - to parse radix 1 numbers. - (condition_term, comma_term): New parse functions. - (shift_term): Support >>>. - (m4_evaluate): Port patch from branch to output radix 1 numbers. - Warn instead of error for most parse problems. - * doc/m4.texinfo (Limits control, Eval): Document these changes. - * NEWS: Document new operators and new command line option. - -2007-01-04 Eric Blake - - * configure.ac (AC_SYS_LARGEFILE): Guarantee large file support. - -2007-01-03 Eric Blake - - * doc/m4.texinfo (Format, Incr): More merges. - (Eval): Ensure C precedence rules are met. - * modules/evalparse.c (BADOP, INVALID_OPERATOR): New enumerators. - (not_term, logical_not_term): Delete; these are same precedence - as other unary operators. - (equality_term): New; these are lower precedence than relational - operators. - (eval_lex, simple_term, m4_evaluate): Recognize forbidden C - operators for better error messages. - (logical_or_term, logical_and_term): Short-circuit out the error - of division by zero. - (unary_term): Allow consecutive unary operators. - * modules/m4.c (int2numb, numb2int): Delete; these potentially - truncate bits. - (numb_not, numb_eor, numb_ior, numb_and): Update callers. - * modules/mpeval.c (reduce1, reduce2): Protect macros better. - * NEWS: Document this change. - -2006-12-27 Eric Blake - - * doc/m4.texinfo (Substr, Patsubst): Merge more sections from the - branch. - * modules/m4.c (substr): Merge from branch. - -2006-12-26 Eric Blake - - * doc/m4.texinfo (Changesyntax): Check for regressions with - changesyntax(W=...). - -2006-12-22 Eric Blake - - * m4/m4module.h (m4_set_syntax): Change signature. - * modules/gnu.c (m4_resyntax_encode_safe): Reduce error to - warning. - (changesyntax): Likewise, and update caller. - * m4/m4private.h (m4_syntax_table): Add orig member. - * m4/syntax.c (m4_set_quotes, m4_set_comment): Merge from branch. - Don't set is_single_quotes and is_single_comments when the begin - character is shadowed by another syntax type. - (m4_syntax_create): Populate default syntax table. - (add_syntax_attribute): Don't lose quote assignment. - (remove_syntax_attribute): Only allow removing rquote or ecomm. - (add_syntax_set, subtract_syntax_set, set_syntax_set) - (reset_syntax_set): New helper routines. - (m4_set_syntax): Alter semantics - NUL key reverts entire syntax - to default, and empty chars reverts that key to default. - (check_is_single_quotes, check_is_single_comments): New helper - routines. - * modules/m4.c (changecom): Merge from branch. - * m4/input.c (m4__next_token): Rearrange token recognition order - to macro, quote, comment, in order to match traditional - implementations. - * src/freeze.c (reload_frozen_state): Update caller. - * doc/m4.texinfo (Changequote, Changecom): Merge from branch, with - modifications. - (Changeresyntax): Revise to match style of surrounding sections - and add more examples. - (Changesyntax): Likewise, and update to new semantics. - * NEWS: Document this change. - - * doc/m4.texinfo (Operation modes): Avoid underfull hbox. - (M4wrap, Eval, Errprint): Fix typos. - (Divnum): Not necessary to redivert in example. - -2006-12-21 Eric Blake - - * doc/m4.texinfo (Len, Index macro, Regexp): More section merging - from branch. - -2006-12-19 Eric Blake - - * modules/m4.h (m4_sysval_flush_func): Adjust prototype. - * modules/m4.c (m4_sysval_flush): Add parameter, so that m4exit - can track write errors without all other callers warning multiple - times. - (sysval_flush_helper): New function. - (dumpdef, syscmd, errprint, m4exit): Adjust callers. - * modules/gnu.c (esyscmd): Likewise. - * tests/others.at (stdout closed, stdout full): Error message - update. - -2006-12-16 Eric Blake - - * src/main.c: Fix missing include. - - * src/main.c (main): Check for errors when closing stdin. - * modules/m4.c (m4exit): Missed part of previous patch: flush - stdin before a successful exit. - Reported by Ralf Wildenhues. - -2006-12-14 Eric Blake - - * modules/m4.c (m4_sysval_flush): Flush stdin before exiting, as - required by POSIX. - * tests/others.at (stdin seekable): New test. - -2006-12-09 Ralf Wildenhues - - * doc/m4.texinfo: Fix some typos. - -2006-12-04 Eric Blake - - * doc/m4.texinfo (Undivert, Divnum, Cleardivert): Merge more doc - sections. - (Modules): Make style consistent. - -2006-11-16 Eric Blake - - * bootstrap: Relax m4 requirement, thanks to... - * configure.ac (Gettext support): ...this workaround to the 1.4.4 - bug. Undoes restriction added on 2006-11-09. - - * tests/builtins.at (esyscmd, syscmd): Redo, since spilled - diversions are now closed when not active. - (divert): Remove check now in the manual. - * tests/others.at (stderr closed): Likewise. - (stdout closed): Add a check. - * doc/m4.texinfo (Include, Search Path, Diversions, Divert): Sync - more docs with branch. - -2006-11-14 Eric Blake - - Remerge sparse diversion handling from branch. - * ltdl/m4/gnulib-cache.m4: Replace avltree-list with - avltree-oset. - * m4/output.c (diversion_table): Change type to gl_oset_t. - (m4_output_init, m4_output_exit, cleanup_tmpfile, make_room_for) - (m4_make_diversion, insert_diversion_helper, m4_insert_diversion) - (m4_undivert_all, m4_freeze_diversions): Adjust all callers. - (div0, diversion_storage): New variables. - (diversions, equal_diversion_CB): Deleted. - (threshold_diversion_CB): New callback. - (m4_tmpname, m4_tmpopen, m4_tmpclose, m4_tmpremove): New - functions. - (m4_tmpfile): Move cloexec action here. - - * m4/resyntax.c (m4_regexp_syntax_encode): Avoid bug with signed - char. - -2006-11-13 Eric Blake - - Add several new command line options. - * src/main.c (usage): Update. - (OPTSTRING, long_options): Add --pushdef, --popdef, --gnu, - --traceon, --traceoff, --syncoutput, --warnings, --unload-module. - Make --regexp-syntax argument optional. - (main): Support new options. Fix regression in interactive - behavior from Nov 8. - * m4/m4private.h (M4_OPT_SYNCOUTPUT_BIT): Rename from - M4_OPT_SYNC_OUTPUT_BIT. - * m4/m4module.h (m4_context_opt_bit_table): Rename sync_output to - syncoutput, to match option. - (m4_parse_truth_arg): New prototype. - * m4/utility.c (m4_parse_truth_arg): Implement it. - * m4/output.c (m4_shipout_text): Adjust sync_output caller. - * modules/gnu.c (syncoutput): Adjust sync_output caller, and use - m4_parse_truth_arg. - * doc/m4.texinfo (Operation modes, Dynamic loading features) - (Preprocessor features, Limits control, Debugging options) - (Command line files): Update documentation. - * tests/builtins.at (mkstemp): Simplify. - * tests/macros.at (Command line pushdef): New test. - (Command line define): Improve. - * tests/options.at (--traceon and --traceoff, --syncoutput): New - tests. - (POSIXLY_CORRECT): Likewise. - (deprecated options): Augment. - (--regexp-syntax): Update, now that -r takes optional arg. - * NEWS: Reformat. Document new options. - -2006-11-11 Eric Blake - - One step closer to allowing C++ compilation - don't blindly - convert between char* and unsigned char*. - * m4/m4module.h (m4_set_syntax): Change signature. - * m4/m4private.h (m4_string): Use signed char. - (m4_get_syntax_lquote, m4_get_syntax_rquote, m4_get_syntax_bcomm) - (m4_get_syntax_ecomm): No longer a need to cast. - * m4/syntax.c (m4_set_syntax, m4_syntax_create, m4_set_quotes): - Reflect this change. - * m4/macro.c (expand_argument): Simplify. - (expand_token): Use proper type. - * src/freeze.c (reload_frozen_state): Likewise. - * m4/input.c (MATCH, match_input): Likewise. - * modules/m4.c (translit): Likewise. - * modules/gnu.c (substitute): Simplify. - - * m4/macro.c (trace_format): Use canonical type name. - * m4/output.c (m4_freeze_diversions): Likewise. - * src/freeze.c (produce_module_dump, dump_symbol_CB) - (produce_frozen_state): Likewise. - * m4/m4private.h (to_uchar): Grab from branch. - * m4/input.c (string_peek, string_read): Use it. - * m4/utility.c (skip_space): Likewise. - * src/main.c (main): Likewise. - * doc/m4.texinfo (Translit): Remerge from branch. - * tests/builtins.at (translit): Test 8-bit range. - * modules/m4.c (m4_expand_ranges): Merge from branch. - -2006-11-09 Eric Blake - - * bootstrap: Validate that installed M4 is powerful enough. - Reported by Gary V. Vaughan, analyzed by Stepan Kasal. - -2006-11-08 Eric Blake - - Merge deferred handling of -D option from branch. - * doc/m4.texinfo (Debugging options, Preprocessor features) - (Dynamic loading features, Operation modes, Invoking m4): - Document this change. - * src/main.c (OPTSTRING): Specify in-order processing. - (process_file): New function. - (main): Use it to interleave files and deferred options. - * tests/macros.at (Command line define): New test. - * tests/generate.awk: Allow '@comment file' as first example - within a node. - * tests/options.at (option grouping): Update to reflect actual - POSIX semantics. - (file names): New test. - -2006-11-07 Eric Blake - - * m4/output.c (cleanup_tmpfile, m4_insert_diversion_helper): Check - for failure. - - * tests/builtins.at (m4exit): New test; failed on cygwin before - this patch. - * m4/output.c (cleanup_tmpfile): Close files before removing - directory. - (make_room_for, m4_output_exit): Ensure that atexit handler - invoked from m4_error sees consistent state. - - * doc/m4.texinfo (Errprint): Merge another doc node. - * tests/builtins.at (dumpdef, errprint): New tests. - * modules/m4.c (errprint): Merge from branch: flush before - printing to stderr. - -2006-11-02 Eric Blake - - * bootstrap: Update bootstrap requirement wording. - Reported by Bruno Haible. - -2006-10-31 Eric Blake - - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool --import - strstr'. - * doc/m4.texinfo (Translit): Merge from branch. - * modules/m4.c (divert, substr): Ignore excess arguments. - (index, translit): Merge from branch. - * tests/builtins.at (translit): Add a test. - -2006-10-30 Eric Blake - - * m4/m4private.h (m4_get_symbol_value_module): Delete accidental - checkin. - * m4/symtab.c (m4_get_symbol_value_module): Likewise. - - * modules/m4.c (m4_make_temp): Make safe across libtool. - * m4/symtab.c (dump_symbol_CB) [DEBUG_SYM]: Avoid warnings. - * configure.ac (--with-modules): Accomodate changed module - location when doing './configure --enable-debug'. - -2006-10-28 Eric Blake - - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool --import - config-h.' - -2006-10-27 Eric Blake - - * bootstrap (gnulib): No longer a need to patch after gnulib-tool - --update. - * configure.ac (AM_GNU_GETTEXT_VERSION): Bump requirement to - 0.16, since 0.15 is incompatible with our automake requirement. - - * m4/macro.c (expand_argument): Fix missing initialization. - * m4/m4private.h (struct m4_symbol_value): Store entire - m4_builtin, not just the func. - (m4_get_symbol_value_func): Update. - (m4_get_symbol_value_builtin, m4_set_symbol_value_builtin): New - fast accessors. - * m4/m4module.h (m4_get_symbol_value_builtin) - (m4_get_symbol_builtin): New prototypes. - (m4_set_symbol_value_func): Delete, replace with... - (m4_set_symbol_value_builtin): New function. - (m4_builtin_find_by_name): Change signature. - * m4/symtab.c (m4_symbol_value_print): Simplify. - (m4_get_symbol_value_func): Update. - (m4_get_symbol_value_builtin): New function. - (m4_set_symbol_value_func): Delete, replace with... - (m4_set_symbol_value_builtin): New function. - (dump_symbol_CB) [DEBUG_SYM]: Simplify. - * m4/builtin.c (m4_builtin_find_by_name): Change signature. - * m4/input.c (struct m4_input_block): Remove unused trace member. - (m4_push_builtin, builtin_print, init_builtin_token): Update - callers. - * m4/module.c (install_builtin_table): Likewise. - * src/freeze.c (reload_frozen_state): Likewise. - * modules/gnu.c (builtin): Make it possible to retrieve a builtin - token, even after the builtin has been undefined. - * doc/m4.texinfo (Builtin): Document new capability. - * NEWS: Likewise. - - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool --import - tempname'. - * modules/m4.c (m4_make_temp): Use it. - * tests/builtins.at (mkstemp, mkdtemp): Update message wording. - -2006-10-27 Ralf Wildenhues - - * Makefile.am (dist_pkgdata_DATA): Distribute recently-added - files. - -2006-10-26 Eric Blake - - Silence -O2 -Wall -Wwrite-strings warnings. - * m4/m4private.h (m4_symbol_value): Const-ify text. - * m4/m4module.h (m4_get_symbol_value_text) - (m4_get_symbol_value_placeholder, m4_set_symbol_value_text) - (m4_set_symbol_value_placeholder): Likewise. - * m4/macro.c (expand_token, expand_argument, expand_macro): Fix - fallout. - * m4/symtab.c (m4_symbol_value_delete, m4_symbol_value_copy) - (m4_get_symbol_value_text, m4_get_symbol_value_placeholder) - (m4_set_symbol_value_text, m4_set_symbol_value_placeholder): - Likewise. - * modules/format.c (format): Likewise. - * src/main.c (main): Likewise. - * src/freeze.c (produce_symbol_dump, dump_symbol_CB): Likewise. - * modules/shadow.c (shadow, test): Likewise. - * m4/output.c (m4_make_diversion): Don't hold on to empty - diversions. - (m4_output_init, make_room_for, m4_undivert_all): Don't type-pun. - (m4_freeze_diversions): Likewise. Don't use uninitialized - variable. - - Convert diversions to list instead of sparse array, part 2. - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool --import - avltree-list'. - * m4/output.c (m4_diversion): Add next pointer and divnum members. - (diversion_table): Convert to a list instead of a sparse array. - (free_list): Maintain free list of reclaimed diversions. - (equal_diversion_CB, cmp_diversion_CB): New functions. - (m4_output_init): Set up list. - (m4_output_exit): Tear down list. - (make_room_for, m4_undivert_all, m4_freeze_diversions): Change - list iteration. - (m4_make_diversion): Change creation of new diversions. - (m4_insert_diversion_helper): New function, to avoid list - searches. - * tests/builtins.at (divert): The test now passes. - * NEWS: Document this improvement. - - Convert diversions to list instead of sparse array, part 1. - * m4/m4module.h (m4_shipout_text, m4_shipout_string): Use size_t - for length. - * m4/output.c (diversion, total_buffer_size, output_unused): - Track size in size_t. All users changed. - (struct diversion): Reduce size now, to compensate for part 2. - (m4_make_diversion, make_room_for): Avoid malloc overflow. - (m4_output_exit): Fix typo in assert. - (m4_output_init, make_room_for, m4_make_diversion) - (m4_insert_diversion, m4_freeze_diversions): Adjust users of - struct m4_diversion to disambiguate the new union. - * tests/builtins.at (divert): Detect this failure. - -2006-10-25 Eric Blake - - * m4/m4module.h (m4_push_builtin): Add parameter. - * modules/m4.c (defn): Update caller. - * m4/input.c (file_read_init, string_read_init): No longer - needed. - (input_funcs): Change signature of read_func, all callers - updated. - (composite_peek, composite_read, composite_unget), - (composite_print, composite_funcs): New input type. Not yet - fully utilized, but one step closer to fixing defn. - (m4_input_block): Make every input block track current file and - line. Rename some members. Remove unused out_line. Add support - for composite input block. - (input_change): New flag. - (file_peek, file_read, file_clean, file_unget, file_print): - Update callers. - (m4_push_file, m4_push_builtin, m4_push_string_init) - (m4_push_string_finish, m4_push_wrapup, m4_pop_wrapup) - (m4_skip_line, pop_input): Track input block changes. - (m4_pop_wrapup): Avoid overflow. - (init_builtin_token): Handle composite input. - (next_char): Handle input block changes. - * doc/m4.texinfo (Location): Remerge from branch. - - * src/m4.h (includes): Need after all; fixes - regression from yesterday. - - * m4/system_.h (obstack_regrow): New macro. Hopefully glibc will - accept it someday. - * m4/macro.c (expand_macro): Avoid referencing invalid memory. - Handle nesting the argc obstack. - (expand_token): Avoid unnecessary malloc. - (collect_arguments): Copy name before invalidating it. - (argc_stack, argv_stack): New variables. - (m4_macro_expand_input): Initialize argc and argv stacks once per - file, instead of once per macro. - -2006-10-24 Eric Blake - - * src/m4.h (includes): Add gettext.h, for N_. Assume setlocale. - -2006-10-23 Eric Blake - - * doc/m4.texinfo (Macro Arguments, Incompatibilities): Remerge - from branch regarding stripped leading whitespace. - - * modules/m4.c (includes): Use safe headers even when configured - with --enable-assert. - (m4_builtin_table, m4_make_temp): Work around fact that mkstemp is - #defined as mkstemp_safer. - -2006-10-21 Eric Blake - - * modules/m4.c (m4_make_temp): Change signature. - (maketemp, mkstemp): Update callers. - * modules/m4.h (m4_make_temp_func): New export. - * modules/gnu.c (mkdtemp): New macro. - * doc/m4.texinfo (Operation modes): Document interaction with - --safer. - (Mkdtemp): New node. - * tests/builtins.at (mkdtemp): New test. - (mkstemp): Check for umask effect. - * NEWS: Document new builtin. - - * tests/generate.awk (normalize): Update recognition of trailing - spaces in tests. - * doc/m4.texinfo: Minor formatting fixes from branch. - (Foreach, Improved foreach): Merge from branch. - * examples/foreach.m4: Merge from branch. - * examples/foreachq.m4: New file from branch. - * examples/foreach2.m4: Likewise. - * examples/foreachq2.m4: Likewise. - - * doc/m4.texinfo (titlepage): Add myself as author. - * src/main.c (AUTHORS): Likewise. - -2006-10-19 Eric Blake - - * modules/m4.c (m4_make_temp, mkstemp): New functions. - (maketemp): Add POSIX behavior and a warning. - * tests/others.at (maketemp): Move this test... - * tests/builtins.at (mkstemp): ...to here, and beef up. - * tests/options.at (--safer): Update to new warning message. - * doc/m4.texinfo (Mkstemp): Sync from branch. - (Extensions): Update maketemp behavior. - * NEWS: Document that maketemp now always warns. - - * tests/generate.awk: For ease of doc-writing, simplify selection - of '-Ipath/to/examples' to '@comment examples'. - * examples/forloop.m4: Simplify. - * examples/forloop2.m4: New file. - * examples/quote.m4: New file. - * doc/m4.texinfo (Improved forloop): New node. - (Manual): Clarify use of examples directory. - (Shift, Forloop): Resync from branch. - (Include, Location): Update to new usage of examples directory. - - * m4/system_.h (includes): Pick up before checking for - _POSIX_VERSION. - (gettext_noop): Don't define here, let gettext.h do it instead. - * po/POTFILES.in: Update entries to reflect gnulib imports. - -2006-10-16 Eric Blake - - * ltdl/m4/gnulib-cache.m4: Augment with 'gnulib-tool --import - configmake'. - * configure.ac (AM_INIT_AUTOMAKE): Bump requirement to 1.10a, for - pkglibexecdir support. - * Makefile.am (m4_libm4_la_SOURCES, m4/pathconf.h): No longer - worry about pathconf.h, now that gnulib does it for us. - (pkgmodincludedir): Simplify. - (pkglibexecdir): Delete, now that automake does this. - * m4/module.c (m4__module_init): Use PKGLIBEXECDIR. - * src/main.c (usage): Likewise. - * m4/symtab.c (m4_symbol_value_groks_macro): Fix typo. - - * doc/m4.texinfo: Port some changes from the branch. - (Invoking m4): Promote to a chapter, instead of a section of - Preliminaries. - (Operation modes, Dynamic loading features, Preprocessor features) - (Limits control Frozen state, Debugging options) - (Command line files): Subdivide into new sections. - (Cleardivert): Rename from cleardiv. - -2006-10-14 Eric Blake - - * tests/others.at (stdin closed): Update to match previous patch. - - * m4/input.c (file_clean): Don't close stdin twice, POSIX says it - is not portable. - Reported by Ralf Wildenhues. - - * modules/m4.c (undivert): Merge from branch. - * doc/m4.texinfo (Improved fatal_error): Fix typo. - (Improved exch): New node, copied from branch. - (Improved cleardivert): Update from branch. - * THANKS: Update. - -2006-10-13 Eric Blake - - * configure.ac (AC_CONFIG_HEADERS): Name the template config.hin, - not config-h.in. - * modules/gnu.c (builtin, indir): Transparently handle builtin - tokens from defn. - * doc/m4.texinfo (Indir, Builtin): Remerge from branch. - * m4/input.c (m4_pop_wrapup): Display debug message when switching - to wrapped text. - (m4_input_init): No need to use empty file any more. - (file_print): Display correct file name. - * m4/utility.c (m4_error, m4_warn): Ensure we don't try to - dereference a NULL file name. - * m4/m4module.h (m4_pop_wrapup): New parameter. - (m4_symbol_value_groks_macro, m4_symbol_groks_macro): New - prototypes. - * m4/m4private.h (m4_symbol_value_groks_macro): Faster version. - * m4/symtab.c (m4_symbol_value_groks_macro): New method. - * src/main.c (main): Adjust caller. - * tests/options.at (--debugmode): Test more output from -dV. - -2006-10-12 Eric Blake - - * m4/input.c (m4_print_token) [DEBUG_INPUT]: Modernize. - - * m4/m4private.h (m4__next_token_is_open): New prototype. - * m4/m4module.h (m4_push_single): Delete; push_string is an - adequate interface, and removing support for this simplifies the - input engine. - (m4_push_wrapup): New parameter. - (m4_is_syntax): Delete; m4_has_syntax is sufficient. - (M4_SYNTAX_LQUOTE, M4_SYNTAX_BCOMM, M4_SYNTAX_MASKS): Make - start-quote and start-comment exclusive from other syntax - categories. - * m4/syntax.c: Likewise. - * m4/input.c (input_funcs): Make polymorphic without requiring - clients to know whether they are located at isp. All users - changed. - (file_names): New variable. - (m4_input_init): Initialize it. - (m4_push_file): Use it. - (m4_input_exit): Free it after use. - (m4__next_token): Simplify slightly. - (m4__peek_token): Rename and simplify... - (m4__next_token_is_open): ... to this. In particular, this - allows us to avoid a double ungetc, which POSIX doesn't - guarantee. - (struct m4_input_block, m4_push_single, single_peek, single_read): - Remove support for single characters, as the input engine now - guarantees we don't need it. - (file_unget, string_unget, m4_input_print, unget_input): - Strengthen assertions. - (file_init_funcs, file_read_init): New for file reading. - (string_init_funcs, string_read_init): New for wrapped text. - (m4_push_string_init, m4_push_string_finish, m4_push_wrapup): - Support wrapped text with locations. - (m4_skip_line): Support dnl across include file boundary. - (peek_char): Don't pop input when peeking. - (file_peek): Peek can be called at the end of the file. - (string_read): Don't read beyond string bounds. - * m4/macro.c (expand_token, collect_arguments): Update callers. - (expand_macro): Report errors at location of open parenthesis. - (expand_token, expand_argument, process_macro): Avoid negative - array dereferences with m4_has_syntax. - * m4/utility.c (skip_space): Likewise. - * modules/m4.c (m4wrap): Update caller. - * tests/builtins.at (__file__, __line__, dnl): New tests. - * tests/options.at (--debugmode): Normalize the output. - * doc/m4.texinfo (Macro Arguments, Dnl, History, Location): - Remerge recent changes from branch. - (Improved fatal_error): New node from branch. - -2006-10-11 Eric Blake - - * src/main.c (usage, long_options): Add --debugmode as an alias - for --debug, to match macro name. - * tests/options.at (--debugmode): Rename from --debug, and test - for new alias. - (--discard-comments): Augment test. - * doc/m4.texinfo (Invoking m4, Debugmode): Document this. - * NEWS: Likewise. - -2006-10-10 Eric Blake - - Trace improvements: debugmode(c) was always printing the last two - lines paired, combine them; and show non-text expansions. - * m4/macro.c (trace_prepre): Update to show what the macro will - expand to. - (trace_pre): No need to special-case on debugmode(c). - (trace_post): Likewise. Also, show non-text expansions. - (expand_macro): Update caller. Collecting arguments can change - debug mode, so cache values beforehand. - (trace_format): Remove support for unused %l%S%r, and fix support - for %z to match gcc's attribute((printf)). - (trace_header): Update caller. - * m4/input.c (struct m4_input_block): Rename from input_block. - (struct input_funcs): Add print_func member. - (file_print, builtin_unget, builtin_print, string_print) - (m4_input_print): New functions. - (m4_push_string_finish): Change return type. - (m4_push_file): Fix missing use of close parameter. - * m4/debug.c (m4_debug_decode): Don't clear pending traces. - * m4/m4module.h (m4_input_print): New prototype. - * tests/builtins.at (debug, esyscmd, multiquotes, syscmd): Update - to match behavior change. - * tests/options.at (--debug): Likewise. - * tests/macros.at (Propagation of traceon) - (Propagation of --trace): Likewise. - * tests/others.at (stderr closed, stdout closed, stdin closed): - Likewise. - * doc/m4.texinfo (Forloop): Simplify. - (Trace): Update to changed behavior. - (Debugmode): Document this change. - * src/main.c (usage): Likewise. - * NEWS: Likewise. - -2006-10-09 Eric Blake - - * m4/path.c (m4_include_env_init): Don't alter result of getenv. - Reported by Ralf Wildenhues. - - * modules/gnu.c (gnu_buf): Rename from buf to silence -Wshadow. - -2006-10-07 Eric Blake - - * m4/m4module.h (m4_set_exit_failure): New prototype. - * m4/utility.c (m4_set_exit_failure): New function. - * modules/m4.c (m4exit): Use it to avoid yet another global - variable export in libm4. - -2006-10-06 Eric Blake - - * m4/output.c (cleanup_tmpfile): Exit nonzero on failure to clean - up. - * tests/others.at (stdout closed): Fix final check. - - Replace uses of tmpfile with clean-temp, since tmpfile is - incompatible with closeout. - * tests/builtins.at (esyscmd, syscmd): Don't use pipe; it loses - exit status of m4. - * tests/others.at (stderr closed): Likewise. - * tests/testsuite.at (M4_ONE_MEG_DEFN): Actually hit one meg. - * ltdl/m4/gnulib-cache.m4: Augment with gnulib-tool --import - clean-temp. - * m4/output.c [!HAVE_TMPFILE]: Delete dead code. - (m4_tmpfile, cleanup_tmpfile): New functions. - (make_room_for, m4_insert_diversion): Use clean-temp module. - * configure.ac (AC_CHECK_FUNCS_ONCE): No longer check for - tmpfile. - * doc/m4.texinfo (Diversions): Document new use of $TMPDIR. - - * m4/utility.c (m4_numeric_arg): Merge from branch. - * modules/gnu.c (debuglen): New builtin. - * src/main.c (usage, ARGLENGTH_OPTION, long_options, main): - Rename --arglength to --debuglen. - * tests/options.at (--arglength): Rename to --debuglen. - (deprecated options): Augment test. - * doc/m4.texinfo (Invoking m4): Document the name change. - (Debugmode): Rename from Debug Levels. - (Debugfile): Rename from Debug Output. - (Debuglen): New node. - * NEWS: Document these changes. - - * modules/m4.c (m4exit): Fix typo. Ensure desired exit status in - case closing a module exits. - - * modules/m4.c (m4exit): Merge from branch. - * m4/m4.c (m4_delete): Avoid assertion triggered by last patch. - -2006-10-05 Eric Blake - - * ltdl/m4/gnulib-cache.m4: Augment with gnulib-tool --import - closeout. - * Makefile.am (m4_libm4_la_DEPENDENCIES): Add missing dependency. - * src/main.c (main): Close stdout on exit. - * m4/debug.c (set_debug_file): Check for write failure. - * m4/m4.c (m4_delete): Don't mask write failure. - * tests/testsuite.at (AT_CHECK_M4): Allow tracing by expanding - macros before calling AT_CHECK. - (M4_ONE_MEG_DEFN): New helper macro. - * tests/others.at (stdout full): New test. - (stderr closed, stdin closed, stdout closed): Augment. - * tests/builtins.at (syscmd): New test. - (esyscmd): Augment. - -2006-10-04 Eric Blake - - * tests/builtins.at: Alphabetize tests. - * tests/testsuite.at (AT_CHECK_M4): Allow choosing stdin. - * tests/generate.awk (new_test): Fix underquoting. - * tests/others.at (maketemp): Rename from misc. - (stdin closed, stdout closed, stderr closed): New tests. - -2006-10-03 Eric Blake - - Avoid all global variables in modules, so that --disable-static - can work on cygwin. - * examples/incl.m4: New file, from branch. - * Makefile.am (dist_pkgdata_DATA): Distribute it. - * doc/m4.texinfo (Location): Merge this section from branch. - (Include): Update the test. - * tests/generate.awk (new_test): Allow for VPATH build - pre-processing of expected __program__ output. - * m4/m4module.h (m4_current_diversion, m4_output_current_line): - Avoid global variables. - (m4_context_field_table): Add current_diversion, output_line. - (m4_output_init, m4_make_diversion): Add parameter. - (m4_get_program_name, m4_set_program_name): New accessors. - * m4/m4private.h (m4_get_current_diversion), - (m4_set_current_diversion, m4_get_output_line) - (m4_set_output_line): New accessors. - * m4/utility.c (m4_get_program_name, m4_set_program_name): New - methods. - * modules/m4.c (divnum, divert): Adjust callers. - * modules/gnu.c (__program__): Likewise. - * m4/output.c (m4_output_init, m4_make_diversion) - (m4_freeze_diversions, m4_shipout_text, m4_make_diversion) - (m4_insert_diversion): Likewise. - * m4/input.c (file_clean, m4_push_file): Likewise. - * src/freeze.c (reload_frozen_state): Likewise. - * src/main.c (main, usage): Likewise. - - Partially plug memory leak when unloading gnu module. - * tests/modules.at (unload gnu module): New test. - * modules/gnu.c (gnu_LTX_m4_finish_module): New function. - (m4_regexp_compile): Move static storage to module visibility. - * tests/options.at (--debug): Adjust to new output. - -2006-09-29 Eric Blake - - Even when not the first option, --help can't have side effects. - * tests/options.at (--debugfile): Detect bugs in this area. - * tests/testsuite.at (AT_CHECK_M4): Avoid a process when ignoring - stderr. - * src/main.c (main): Fix it by deferring debugfile change. Also, - defer closing streams until after module tracing is done. - * modules/gnu.c (debugfile): Make message consistent with command - line. - * doc/m4.texinfo (Invoking m4): Touch up the documentation. - * NEWS: Document this fix. - - * modules/m4.c (dnl): Include macro name in warning message. - * m4/input.c (m4_skip_line): Add parameter. - * m4/m4module.h (m4_skip_line): Likewise. - * src/main.c (usage): Update wording. - * doc/m4.texinfo (Inhibiting Invocation): Add xfailed test until - issue of blind macros vs. POSIX is resolved. - (Dnl): Merge another node from branch. - - * ltdl/m4/gnulib-cache.m4: Augment with gnulib-tool --import - xstrtol. - * m4/system_.h (N_): Define. - * src/main.c (main): Validate numeric arguments. - (size_opt): New function, idea borrowed from coreutils. - * m4/macro.c (expand_macro): -L0 implies no limit. - * doc/m4.texinfo (Invoking m4): Document this change. - * NEWS: Likewise. - * tests/options.at: (--arglength, --nesting-limit) - (--regexp-syntax): New tests of argument validation. - -2006-09-28 Eric Blake - - * tests/options.at: Alphabetize the tests. - -2006-09-27 Eric Blake - - * m4/m4module.h (m4_symbol_value_print, m4_symbol_print): Add - another parameter to print module info. - * m4/macro.c (trace_pre): Adjust caller. - * modules/m4.c (M4BUILTIN_HANDLER): Likewise. - * doc/m4.texinfo (Dumpdef, Debug Levels): Document this. - * NEWS: Document this. - - * ltdl/m4/gnulib-cache.m4: Augment with gnulib-tool --import - strnlen. - * m4/symtab.c (symbol_value_print): Rename to... - (m4_symbol_value_print): ...this, and... - (m4_symbol_print): Update to allow -L length truncation. Now - truncation also affects dumpdef output and builtin names. - * m4/m4private.h (nesting_limit, max_debug_argument_length): - Switch to size_t. - * m4/m4module.h (m4_symbol_print): Add parameter. - (m4_symbol_value_print): New function. - * modules/m4.c (dumpdef): Allow length truncation. - * m4/macro.c (trace_pre): Use m4_symbol_print, rather than - repeating code. - * doc/m4.texinfo (Invoking m4): Document -l better. - (Dumpdef, Debug Levels): Document the effect of -l. - * NEWS: Document this change. - - * modules/m4.c (m4_dump_symbols, errprint, m4wrap) - (m4_expand_ranges): Ensure we aren't picking up partial object on - obstack. - * modules/stdlib.c (setenv): Allow extra arguments. - * modules/time.c (ctime): Avoid side effect in call to - obstack_grow. - * modules/gnu.c (m4_regexp_substitute): Likewise. - (renamesyms): Avoid extra obstack_init. - * src/freeze.c (reload_frozen_state): Remove debug comment. - (produce_frozen_state): Simplify fprintf to puts where possible. - * modules/modtest.c (modtest_init, modtest_finish): Likewise. - * modules/import.c (import, symbol_fail, modules_fail): Likewise. - * m4/macro.c (trace_flush): Likewise. - * m4/debug.c (m4_debug_message_prefix): Likewise. - * m4/path.c (include_dump): Likewise. - * m4/module.c (module_remove): Likewise. - (install_builtin_table): Simplify malloc and string - concatenation. - -2006-09-26 Eric Blake - - * m4/m4module.h (m4_symbol_print): New prototype. - (M4_DEBUG_TRACE_STACK): New enumerator. - (m4_is_debug_bit): Allow use without requiring m4private.h. - * m4/symtab.c (symbol_value_print, m4_symbol_print): New - functions. - * modules/m4.c (dump_symbol_CB, m4_dump_symbols): Speed up - callback. - (dumpdef): Allow printing pushdef'd stacks. - * m4/debug.c (m4_debug_decode): Add new 's' debug mode. - * src/main.c (usage): Document it. - * doc/m4.texinfo (Dumpdef, Debug Levels): Likewise. - * NEWS: Likewise. - - * configure.ac (AC_CONFIG_HEADERS): Place with other - gnulib headers. - * Makefile.am (AUTOMAKE_OPTIONS): Add nostdinc, to reduce length - of lines during make. - (AM_CPPFLAGS): Remove unneeded include path. - (src_m4_CPPFLAGS): Remove redundant include path. - * m4/system_.h Make preprocessor indentation consistent. - (M4_DIRSEP_CHAR, M4_PATHSEP_CHAR, M4_GNUC_FORMAT): Remove unused - macros. - (UNIX, W32_NATIVE, OS2): Update platform recognition macros from - branch. - (M4_GNUC_PRINTF, M4_GNUC_SCANF, M4_GNUC_NORETURN) - (M4_GNUC_CONST, M4_GNUC_UNUSED): Mangle names properly for header. - (bool, true, false): Don't undefine here; stdbool takes care of - that. - * src/m4.h (includes): Assume config.h, and several standard - headers. - (__CYGWIN__, WIN32): Don't define here; let system.h do it. - * m4/m4private.h: Assume config.h. - * m4/output.c: Likewise. - * m4/path.c: Likewise. - * m4/resyntax.c: Likewise. - * m4/utility.c: Likewise. - * modules/gnu.c: Likewise. - * modules/import.c: Likewise. - * modules/load.c: Likewise. - * modules/m4.c: Likewise. - * modules/modtest.c: Likewise. - * modules/mpeval.c: Likewise. - * modules/perl.c: Likewise. - * modules/shadow.c: Likewise. - * modules/stdlib.c: Likewise. - * modules/time.c: Likewise. - * modules/traditional.c: Likewise. - -2006-09-21 Eric Blake - - * doc/m4.texinfo (Invoking m4): Add clarification on option - processing behavior. - * tests/options.at (option grouping): Test this. - * THANKS: Update. - Reported by Mikhail Teterin. - - * bootstrap: Add --force option, based on idea from coreutils. - * README: Document that ./bootstrap and autoreconf are for - developers, and not lightly done in tarballs. - -2006-09-20 Eric Blake - - * src/main.c (usage, OPTSTRING, main): Rename -e to -i. Make - warnings consistent. - (long_options, HASHSIZE_OPTION): Warn on -H. - * doc/m4.texinfo (Invoking m4): Document this. - * tests/options.at (deprecated options): Update. - - Change the default of interactive sessions to match sh. - * src/main.c (usage): Document this. - (enum interactive_choice): New enum. - (main): Use it to defer decision of interactive until after - argument processing. - * doc/m4.texinfo (Invoking m4): Document this. - * NEWS: Likewise, plus add missing mention of -b. - Reported by Stepan Kasal. - -2006-09-19 Eric Blake - - * src/main.c (usage, main, DEBUGFILE_OPTION): Deprecate -o as - well as --error-output; the goal is to add -o/--output in some - future version with semantics like gcc or autom4te. - * doc/m4.texinfo (Invoking m4, Dumpdef, Debug Output, Errprint): - (Extensions): Reflect this update. - (Renamesyms): Add another test. - (Defn): Xfail for now, so that `make check' is happy. - * NEWS: Document this change. - * tests/generate.awk: Mark dynamic loading tests as such. Allow - xfailing tests. - * tests/macros.at (Renamesyms collisions): New test, exposing - renamesyms' coredump. - * tests/options.at (--debugfile, --safer): Update to match - change. - - * m4/debug.c (set_debug_file): Fix regression in -o when stdout - and stderr are same file, introduced 2003-07-23. - * tests/options.at (--debugfile): New test, to catch the bug. - (deprecated options): Test --error-output. - * src/main.c (usage, main, long_options, ERROR_OUTPUT_OPTION): - Deprecate --error-output, and replace it with --debugfile. - * doc/m4.texinfo (Invoking m4, Debug Output, Dumpdef, Errprint): - Document this change. - * NEWS: Likewise. - -2006-09-18 Eric Blake - - * modules/load.c (modules): Rename to... - (m4modules): ...this, since it is an English word with 0 - arguments. - * modules/gnu.c (symbols, m4symbols): Likewise. - * doc/m4.texinfo (Listing Modules): Rename to... - (M4modules): ...this. - (Symbols): Rename to... - (M4symbols): ...this. - (Load, Foreach, Trace, Answers): Update to new spellings. - * NEWS: Document this. - - * modules/m4.c (traceon, traceoff): Change to Solaris semantics, - such that without arguments, the global trace flag is changed - rather than walking the table of all currently-defined macros. - (set_trace_CB): No longer needed. - * m4/m4module.h (m4_set_symbol_name_traced): Add a parameter. - (m4_set_symbol_traced): Delete. - (m4_symtab_create): Nuke the nuke parameter. - * m4/m4private.h (m4_get_symbol_value): Delete. - * m4/symtab.c (m4_symbol_popdef): No more need for nuke_trace. - (m4_set_symbol_name_traced): Free undefined entries that are no - longer traced. - (symbol_destroy_CB): Update caller. - * m4/m4.c (m4_create): Update caller. - * src/main.c (main): Likewise. - (usage): Fix typo in last commit. - * doc/m4.texinfo: Minor cleanups throughout. - (Debugging, Dumpdef, Trace, Debug Levels, Debug Output): Merge - more nodes from branch. - (Trace): Document new semantics, and how to simulate the old. - * tests/builtins.at (multiquotes): Adjust to new semantics. - * NEWS: Update somewhat. - -2006-09-14 Eric Blake - - Add --safer option, per debian bug 5898. - * src/main.c (usage): Document new option. - (SAFER_OPTION): New enumerator. - (main): Set the option bit. - * m4/m4module.h (m4_context_opt_bit_table): Declare new bit - accessors. - * m4/m4private.h (M4_OPT_SAFER_BIT): New macro. - (m4_get_safer_opt): New accessor. - * modules/gnu.c (esyscmd, debugfile): Disable when --safer. - * modules/m4.c (syscmd, maketemp): Likewise. - * doc/m4.texinfo (Invoking m4, Debug Output, Syscmd, Esyscmd) - (Sysval, Maketemp): Add tests of this. - * tests/options.at (--safer): Likewise. - -2006-09-13 Eric Blake - - * tests/modules.at (AT_CHECK_M4_MODTEST): Use AT_CHECK_M4, for - stderr filtering. - Reported by Ralf Wildenhues. - - Fix installcheck. - * Makefile.am (check_LTLIBRARIES): Build test libraries in the - tests directory, so we can be sure an installed build is not - picking up uninstalled non-test libraries. - (check-local, installcheck-local): Depend on test libraries. - * tests/modules.at (AT_CHECK_M4_MODTEST): Don't use options - after file name. Fix quoting. Remove skipping the test, now - that makefile guarantees test modules will exist. - (Freezing modules, modules: shadow, modules: unload) - (modules: trace): Always put test modules in module path. - (modules: importing): Likewise, and rely on AT_CHECK_M4 for - stderr munging. - * src/main.c (usage): Document default module search path. - (import_environment, frozen_file_to_read, frozen_file_to_write): - Move... - (main): ...here. - * tests/testsuite.at (AT_CHECK_M4): Filter stderr here... - * tests/m4.in: ...not here. - Reported by Ralf Wildenhues. - -2006-09-08 Eric Blake - - * bootstrap: Kill unrelated copy-n-paste code from argument - parsing. Let Makefile generate testsuite. - * Makefile.am (EXTRA_DIST): Remove examples/WWW/man/Makefile. - -2006-09-07 Eric Blake - - * m4/m4module.h (m4_peek_input): No longer export. - (m4_error_at_line, m4_warn_at_line): New prototypes. - (m4_is_symbol_void): New macro. - (m4_push_file): Update prototype. - * m4/m4private.h (m4__peek_token): New prototype. - (M4_TOKEN_OPEN, M4_TOKEN_COMMA, M4_TOKEN_CLOSE): New enumerators. - * m4/utility.c (m4_error_at_line, m4_warn_at_line): New functions. - * src/main.c (main): Allow reading from stdin twice. - * modules/m4.c (include): Adjust to new prototype. - * m4/input.c: General comment cleanup. - (file_peek, file_read, file_unget, push_file): Set end flag on - EOF, so that we don't call getc twice. - (push_file, file_clean): Port fix from branch to avoid closing - stdin prematurely. - (pop_input): Port fix from branch to avoid reading free'd memory - when input ends mid-string. - (m4_pop_wrapup): Port fix from branch to allow multiple m4wraps. - (string_peek, string_read): Always use unsigned char. - (m4_skip_line): Warn when dnl cut short by EOF. - (peek_input): Rename from m4_peek_input. - (match_input): Update signature, to distinguish between `(' token - and multi-char quote or comment beginning with `('. - (m4_input_exit): Cleanup now done in m4_pop_wrapup. - (m4__peek_token): New function, ported from branch. - (m4__next_token): Update to new token types. - * m4/macro.c (expand_token, expand_argument): Use peek_token. - * doc/m4.texinfo (Pseudo Arguments, Defn, Answers): Fix typos. - (Invoking m4): Remerge from branch. - - * Makefile.am ($(TESTSUITE)): Revert patch from 2006-09-05... - (check-local): and put dependency here. - Reported by Ralf Wildenhues. - -2006-09-05 Eric Blake - - * m4/m4module.h (m4_debug_message): New prototype. - (M4_DEBUG_TRACE_MODULE): New debug bit. - * m4/m4private.h (M4_DEBUG_MESSAGE, M4_DEBUG_MESSAGE1) - (M4_DEBUG_MESSAGE2): Delete these macros. - * m4/debug.c (m4_debug_message): New method. - (m4_debug_decode): Add module tracing as flag `m'. - * m4/input.c (m4_push_file, file_clean): Use new method. - * m4/path.c (m4_path_search): Likewise. - * po/Makevars (XGETTEXT_OPTIONS): Likewise. - * m4/module.c (install_builtin_table, install_macro_table) - (m4__module_open, module_close, module_remove): Promote several - module debug messages outside of DEBUG_MODULES. - (m4__module_init, module_remove) [DEBUG_MODULES]: Don't mix - DEBUG_MODULES with normal trace output. - * src/main.c (usage): Document new flag. - * doc/m4.texinfo (Debug Levels): Likewise. - * Makefile.am ($(TESTSUITE)): Add missing dependency. - * tests/m4.in: Neutralize platform-dependent module filenames. - * tests/options.at (--debug): Update expected output. - -2006-09-05 Ralf Wildenhues - - * doc/m4.texinfo: Fix some typos. - * tests/others.at: Likewise. - -2006-09-05 Eric Blake - - * m4/input.c (lex_debug): Remove dead code that broke compilation - with --enable-debug. - * m4/module.c (install_builtin_table, install_macro_table) - (m4__module_init, m4__module_open, module_close) - (module_remove): Fix compilation when --enable-debug. - * m4/output.c (m4_shipout_text): Likewise. - * ltdl/m4/debug.m4 (M4_CHECK_DEBUGGING): Preload all static - libraries when --enable-debug. - * configure.ac (DYNAMIC_MODULES): New variable, to pass - information to testsuite. - (modules to preload): Determine modules after we know whether - shared libraries are supported. - * tests/atlocal.in (DYNAMIC_MODULES): Substitute this into - testsuite. - * tests/testsuite.at (AT_CHECK_DYNAMIC_MODULE): New macro. - * tests/modules.at (Freezing modules, AT_CHECK_M4_MODTEST) - (modules: shadow, modules: unload, modules: importing) - (modules: trace): Use new macro. - * tests/builtins.at (gmp): Likewise. - - * m4/macro.c (expansion_level, macro_call_id): Change to size_t. - All users updated. - (expand_token): Avoid assertion just added to docs. - (expand_macro): Track pending expansions, for when a symbol's - definition changes during argument collection. - (m4_macro_call, process_macro): Operate on symbol value, not - symbol, since symbol may have changed during argument collection. - * m4/m4private.h (m4_symbol_value): Add pending_expansions member. - (VALUE_PENDING, SYMBOL_PENDING, VALUE_DELETED_BIT): New defines. - (m4_get_symbol_value): Add fast macro version. - * m4/m4module.h (M4_BUILTIN_FLAGS_MASK): New enumerator. - (m4_macro_call): Adjust prototype. - * m4/module.c (install_builtin_table): Check that flags are valid - when creating builtin. - * m4/symtab.c (m4__symtab_remove_module_references): Use - m4_symbol_value_delete, rather than inlining it. - (m4_symbol_value_copy): Copy placeholder text. - (symbol_popval): Use m4_symbol_value_delete. - (m4_symbol_value_delete): Implementation was missing when NDEBUG. - Handle pending expansions. - * modules/gnu.c (indir): Update to new prototype. - * doc/m4.texinfo: Fix menus to be consistent with section names. - (Defn): Add test that macro tokens flatten to empty string; - triggered an assert before this patch. - (Ifelse): Merge another node. - (Loops): Split into... - (Forloop, Foreach): New nodes; work is still underway on them. - (Answers): Add more info on foreach macro; work is still underway. - (Indir): Add test that indir collects arguments before looking up - macro. - * TODO: Update based on this patch. - -2006-09-01 Eric Blake - - * m4/m4.c (m4_create): Fix latent bug since 2003-10-08. - * m4/hash.h (m4_free_hash_iterator): New prototype. - * m4/hash.c (struct m4_hash) [!NDEBUG]: Add iter member, to - ensure we don't do unsafe things while iterating. - (HASH_ITER, ITER_CHAIN): New accessor macros. - (m4_hash_new, m4_hash_resize, maybe_grow): Fix malloc typing bug. - (m4_hash_delete, m4_hash_insert): Unsafe while iterating. - (m4_hash_remove) [!NDEBUG]: Enforce safety while iterating. - (m4_get_hash_iterator_next) [!NDEBUG]: Track current iterators, - to catch unsafe actions. - (m4_free_hash_iterator): New function, to avoid memory leaks, and - when debugging, to track safe actions. - (m4_hash_apply): Avoid memory leak. - * m4/symtab.c (m4_symtab_apply): Likewise. - * ltdl/m4/gnulib-cache.m4: Remove getopt from here; it is pulled - in manually to src/ for now. - * tests/builtins.at (gmp): Add keyword module. - * tests/modules.at (Freezing modules, modules: shadow) - (modules: unload, modules: importing, modules: trace): Likewise. - -2006-08-30 Eric Blake - - * m4/utility.c (m4_warn): Factor "Warning" out of messages into - here. - (m4_bad_argc, m4_numeric_arg): Update all callers. - * m4/macro.c (m4_macro_call): Likewise. - * doc/m4.texinfo (Defn, Pushdef): Fix typos in last commit. - (Indir, Builtin, Ifdef): More doc merges. - (Loops): Mention that documenting foreach would be nice. - (Macro Arguments, Defn, Builtin, Ifdef, Ifelse, Changesyntax) - (Include, Eval, Location, M4exit): s/input.m4/stdin/. - * modules/gnu.c (indir, builtin): Warn, not error, on undefined. - (substitute, syncoutput): Update all m4_warn callers. - * modules/m4.c (undefine, popdef, m4_dump_symbols, defn) - (traceon, traceoff): Make warning message consistent. - (define, pushdef): Update all m4_warn callers. - * tests/generate.awk: Choose file name so that documentation can - show command-line behavior. - * tests/builtins.at (define): Update to new wording. - * tests/macros.at (pushdef/popdef): Likewise. - * tests/freeze.at (loading format 1): Likewise. - * tests/modules.at (AT_CHECK_M4_MODTEST): Likewise. - - * doc/m4.texinfo (Undefine, Defn, Pushdef): More doc merges from - the branch. - (Defn): Add failing test case for mixing text and builtin. - (Renamesyms): Improve wording, and identify core dump that needs - fixing. - -2006-08-29 Eric Blake - - * doc/m4.texinfo (Quoting Arguments, Definitions, Define) - (Arguments, Pseudo Arguments): More doc merges from the branch. - (Macro expansion): Turn example into test. - (Pseudo Arguments): Add example of avoiding argument. - * modules/m4.c (undefine, popdef): Accept multiple arguments. - (define, pushdef): Warn on non-text macro name. - (ifelse, m4_dump_symbols, defn, traceon, traceoff): Tweak - warning/error messages. - (ifdef): Ignore extra arguments. - * m4/symtab.c (m4_symbol_value_copy): Avoid memory leak. - (m4__symtab_remove_module_references): Check that there is no leak. - * tests/macros.at (pushdef/popdef): Update to new message. - * tests/builtins.at (define): Likewise. - * tests/freeze.at (loading format 1): Likewise. - * tests/modules.at (AT_CHECK_M4_MODTEST): Likewise. - - * m4/m4private.h (m4_get_syntax_lquote, m4_get_syntax_rquote) - (m4_get_syntax_bcomm, m4_get_syntax_ecomm) [NDEBUG]: Use same type - as accessor function, to avoid compiler warning. - * m4/module.c (m4__module_open): Move declaration of variable to - avoid compiler warning. - * src/main.c (main): Avoid shadowing a global variable. - * src/freeze.c (produce_symbol_dump): Avoid unused variable - warning when NDEBUG. - * tests/options.at (--discard-comments, --import-environment) - (--debug, --prepend-include, --help and --version): Rename tests - to name option tested. - -2006-08-28 Eric Blake - - * m4/utility.c (m4_bad_argc): Move assertion out of hot path... - * m4/module.c (install_builtin_table): ...to here, and add - assertion that blind macros require arguments. - * m4/m4module.h (struct m4_builtin): Document restrictions that - must be met during module loading. - * modules/gnu.c (changeresyntax, changesyntax): These are blind, - so require an argument to avoid triggering assertion. - (debugfile): Tweak error message. - -2006-08-25 Eric Blake - - * m4/m4module.h (M4_BUILTIN_GROKS_MACRO, M4_BUILTIN_BLIND) - (M4_BUILTIN_SIDE_EFFECT): New enumerators. - (struct m4_builtin): New member flags replaces groks_macro_args, - blind_if_no_args. min_args and max_args are now 0-based. - Rearrange members to reduce size on platforms where function - pointers are 64 bits but regular pointers are 32. - (m4_bad_argc): Add argument. - * m4/m4private.h (VALUE_SIDE_EFFECT_ARGS_BIT): New define. - * m4/utility.c (m4_bad_argc): Simplify calculation, and take side - effect into account. - * m4/module.c (install_builtin_table): Adjust all users affected - by this API change. - * m4/macro.c (m4_macro_call): Likewise. - * src/freeze.c (reload_frozen_state): Likewise. - * modules/m4.c (builtin_functions, ifelse, syscmd): Likewise. - * modules/gnu.c (builtin_functions, builtin, esyscmd): Likewise. - * modules/import.c (builtin_functions): Likewise. - * modules/load.c (builtin_functions): Likewise. - * modules/modtest.c (builtin_functions): Likewise. - * modules/mpeval.c (builtin_functions): Likewise. - * modules/perl.c (builtin_functions): Likewise. - * modules/shadow.c (builtin_functions): Likewise. - * modules/stdlib.c (builtin_functions): Likewise. - * modules/time.c (builtin_functions, mktime_functions) - (strftime_functions): Likewise. - * doc/m4.texinfo (Loops): Update test now that shift is blind. - (Macro Arguments): Fix typo in test. - (Patsubst): Fix typo in test. - * modules/gnu.c (m4_regexp_substitute): Don't skip empty match at - end of string. Fix return value when ignore_duplicates. - * tests/builtins.at (patsubst): Fix typo in test. - - * tests/options.at (debug-flags): Update to reflect new message. - (deprecated options, prepend-include, help and version): New - tests. - * tests/testsuite.at (AT_CHECK_M4): Avoid hanging testsuite if - test omits an input file name. - * src/main.c (long_options, main): Add -B/--prepend-include. - (usage): Document it. - (main): `m4 --help --version' now displays help, not version. - * ltdl/m4/gnulib-cache.m4: Augment with gnulib-tool --import - dirname filenamecat. - * m4/m4module.h (m4_add_include_directory): Add parameter. - * m4/m4private.h (m4__include_init): New prototype. - * m4/m4.c (m4_create): Put `.' on path before options are - collected. - * m4/path.c (includes): Assume C89. Use gnulib for file name - management. - (m4__include_init): New function. - (search_path_add): Allow prepending. - (m4_add_include_directory, search_path_env_init): Adjust callers. - (m4_path_search): Relative names now invoke path search, since - `.' might not be first. - * doc/m4.texinfo (Invoking m4, Search Path): Document new option. - -2006-08-25 Bruno Haible (tiny change) - and Eric Blake - - * bootstrap: Run autopoint before gnulib-tool, since autopoint - 0.15 installs macros obsoleted by current gnulib. - -2006-08-25 Eric Blake - - * doc/m4.texinfo (Macro Arguments): Another section merged; - testsuite failures now exposed. - -2006-08-23 Eric Blake - - * doc/m4.texinfo (Quoted strings, Other tokens, Comments) - (Input processing): More doc merges from the branch. - (Regular expression syntax): Add introductory text. - (Inhibiting Invocation): More doc merges from the branch. - (Other tokens): Reorder after comments. - * tests/generate.awk: Allow passing options to doc examples. - -2006-08-22 Eric Blake - - * tests/options.at (debug-flags): New test. - * m4/m4module.h (M4_DEBUG_TRACE_VERBOSE): Make sure this value is - not negative, to distinguish failure in m4_debug_decode. - (m4_debug_decode): Add new parameter. - * modules/gnu.c (regexp): Slight cleanup. - (renamesyms): Ignore excess arguments. - (syncoutput): Make case-insensitive, warn on bad argument. - (debugmode): Factor -+ handling out to... - * m4/debug.c (m4_debug_decode): ...here. - (m4_debug_message_prefix): Fix spacing. - * src/main.c (main): Let -d option adjust flags. - * m4/input.c (file_clean): Avoid printing empty file name. - * doc/m4.texinfo (Syncoutput): Document new range of input. - (Invoking m4): Document use of multiple -d flags. - - Start porting various fixes from the branch that use gnulib. - * ltdl/m4/gnulib-cache.m4: Augment with gnulib-tool --import - binary-io cloexec close-stream fopen-safer getopt gnupload mkstemp - regexprops-generic stdlib-safer unlocked-io. - * m4/debug.c (m4_debug_set_output): Close debug file on exec. - * m4/path.c (m4_path_search): Close input file on exec, reject - empty file name, fix parameter naming. - * m4/output.c (make_room_for): Close diversion file on exec. - (includes): Assume C89 headers. - (tmpfile): For now, we don't want tmpfile-safer, because we want - clean-temp later. - * m4/m4private.h (includes): Use various gnulib headers. - * doc/regexprops-generic.texi: Use gnulib's copy. - - * configure.ac (AM_INIT_AUTOMAKE): Bump automake requirement. - * AUTHORS: Add copyright. - * ChangeLog: Likewise. - * README: Likewise. Require automake 1.9b or later. - * HACKING: New file. - * README-alpha: Add copyright. - * THANKS: Likewise. Update. - * doc/STYLE: Add copyright, and tweak for changed directories. - * modules/README: Add copyright, and tweak for libtool version. - * examples/COPYING: New file. - * examples/WWW/COPYING: Likewise. - * examples/WWW/m4lib/COPYING: Likewise. - * modules/shadow.m4: Add copyright. - * modules/perl.m4: Likewise. - * modules/modtest.m4: Likewise. - * modules/stdlib.m4: Likewise. - * modules/time.m4: Likewise. - * modules/time2.m4: Likewise. - * po/Makevars: Likewise. - * tests/iso8859.m4: Likewise. - * tests/m4.in: Likewise. - * NEWS: Add (C) to copyright. - * TODO: Likewise. - * m4/system_.h: Likewise. - * tests/atlocal.in: Likewise. - * tests/builtins.at: Likewise. - * tests/freeze.at: Likewise. - * tests/generate.awk: Likewise. - * tests/macros.at: Likewise. - * tests/modules.at: Likewise. - * tests/options.at: Likewise. - * tests/others.at: Likewise. - * tests/testsuite.at: Likewise. - * m4/utility.c: Spell out copyright years. - * src/main.c: Likewise. - - * doc/m4.texinfo (Bugs, Manual, Syntax): Sync from branch. - -2006-08-21 Eric Blake - - * configure.ac (AC_CHECK_HEADERS_ONCE): Check for . - * modules/gnu.c (esyscmd): Use -1 for failure. Set sysval to 0 - when no arguments are given, but without losing warning about 0 - arguments. - * modules/m4.c (syscmd): Likewise. - (includes): Assume C89. - (m4_sysval): Make static. - (M4_SYSVAL_EXITBITS, M4_SYSVAL_TERMSIGBITS): New macros. - (sysval): Port calculation from branch. - -2006-08-20 Eric Blake - - * m4/macro.c (expand_macro): Move argument check... - (m4_macro_call): ...to here, so indir will warn. - * modules/gnu.c (__program__): New macro, ported from branch. - (builtin): Perform argument check. - (changesyntax): Avoid out-of-bounds read. - - * modules/gnu.c (includes): Assume stdlib.h, errno. - (m4_regexp_compile): Add no_sub parameter, avoid memory leaks. - (substitute): Add caller parameter, avoid out-of-bounds memory - references. - (m4_regexp_substitute, patsubst, regexp, renamesyms): Adjust - callers. - -2006-08-16 Eric Blake - - * po/POTFILES.in: Add more files that contain translatable - strings. - * po/Makevars (XGETTEXT_OPTIONS): Add options to pass more - information to translators. - (USE_MSGCTXT): New var for gettext 0.15. - * m4/input.c (file_clean, m4_push_file, m4__next_token): Start - debug/trace messages in lower case. - * m4/macro.c (expand_argument): Likewise. - * m4/path.c (m4_path_search): Likewise. - * src/main.c (main): Likewise. - -2006-08-14 Eric Blake - - * src/main.c (usage): Document --import-environment. - * doc/m4.texinfo (History, Invoking m4): Synchronize from branch. - -2006-08-11 Eric Blake - - * bootstrap (func_get_translations): Only remove files when doing - full update. - (func_update_po): Avoid CDPATH problems. - -2006-08-10 Eric Blake - - * bootstrap (func_get_translations): New function. - (func_update_po): Borrow ideas from tar to correctly pull in - translations from newer location. - -2006-08-09 Eric Blake - - * bootstrap: Recent gnulib no longer has jm_* macros to worry - about. - * ltdl/m4/gnulib-cache.m4: Augment with gnulib-tool --import - verror. - * m4/m4module.h (M4ERROR, M4WARN): Delete, replaced by... - (m4_error, m4_warn): ... these new prototypes. - (m4_current_file, m4_current_line): Move into context, rather - than leaving as globals. - (m4_insert_file, m4_insert_diversion, m4_freeze_diversions) - (m4_undivert_all, m4_input_init): Now takes context. - * m4/utility.c (m4_error, m4_warn): New functions. - * m4/m4private.h: Assume errno exists. - (struct m4): Move warning_status to a bit flag, - and add exit_status. Adjust accessors accordingly. - * src/main.c (print_program_name_CB): No longer needed. - (main): Use new m4_get_fatal_warnings_opt. - * m4/debug.c: Adjust all callers of M4WARN and M4ERROR, and abort - instead of issuing "INTERNAL ERROR". Pass context when needed, - and use new accessors. - * m4/input.c: Likewise. - * m4/macro.c: Likewise. - * m4/output.c: Likewise. - * m4/utility.c: Likewise. - * modules/evalparse.c: Likewise. - * modules/gnu.c: Likewise. - * modules/load.c: Likewise. - * modules/m4.c: Likewise. - * modules/mpeval.c: Likewise. - * src/freeze.c: Likewise. - * src/main.c: Likewise. - * tests/macros.at: Adjust to new message format. - * tests/builtins.at: Likewise. - * tests/freeze.at: Likewise. - * tests/modules.at: Likewise. - * doc/m4.texinfo: Likewise. - - * configure.ac (AM_GNU_GETTEXT, AM_GNU_GETTEXT_VERSION): Require - newer gettext 0.15. - -2006-08-03 Eric Blake - - * src/stackovf.c (setup_stackovf_trap): Port patch from branch to - gracefully handle ENOSYS. - * TODO: Update. - * THANKS: Update. - -2006-07-28 Eric Blake - - * src/freeze.c (reload_frozen_state): Copy string when creating - placeholder, to avoid memory corruption. - * m4/symtab.c (symbol_popval): Avoid memory leak. - (m4_symbol_rename): Avoid shadowing rename function. - (dump_symbol_CB, symtab_dump) [DEBUG_SYM]: Fix compilation. - * tests/freeze.at (reloading unknown builtin): Add test. - * tests/generate.awk: Capture m4.texinfo line number in - testsuite.log, not just generated.at. - - Port idea from branch that a frozen file can request an unknown - builtin without producing a warning unless the builtin is - actually used. - * m4/m4private.h (m4__symbol_type): Add M4_SYMBOL_PLACEHOLDER. - (m4_is_symbol_value_placeholder, m4_get_symbol_value_placeholder) - (m4_set_symbol_value_placeholder): New accessors. - * m4/m4module.h (m4_is_symbol_placeholder), - (m4_get_symbol_value_placeholder), - (m4_set_symbol_value_placeholder), - (m4_get_symbol_placeholder): Likewise. - * m4/symtab.c (m4_is_symbol_value_placeholder), - (m4_get_symbol_value_placeholder), - (m4_set_symbol_value_placeholder): Likewise. - (dump_symbol_CB): Handle new symbol type. - * m4/macro.c (trace_pre): Likewise. - (m4_macro_call): Warn when invoking a placeholder. - * modules/m4.c (dumpdef): Handle dumping a placeholder. - (defn): Warn when referencing a placeholder. - * src/freeze.c (dump_symbol_CB): Ignore placeholder when - freezing. - (reload_frozen_state): When reloading unknown builtin, install a - placeholder instead of warning. - * tests/freeze.at (loading format 1): Allow warning when - popdef'ing undefined function. - -2006-07-27 Paul Eggert (tiny change) - - * m4/hash.c (m4_hash_string_hash): Don't case-fold in the hash - function. Shift by 7, not 3, for consistency with - gnulib/lib/hash.c. Don't assume hash word is 32 bits. - -2006-07-27 Eric Blake - - * src/main.c (usage): Update to match branch. - (main): Update --version info to distinguish between program name - `m4' and package name `GNU M4'. - (AUTHORS): Translate RenĂ© Seindal's name. - * configure.ac (TIMESTAMP): Remove now-redundant parentheses. - * Makefile.am (doc/m4.1): Update to match branch. - * m4/m4.c (DEFAULT_NESTING_LIMIT): Raise to 1024, to match - branch. - - * m4/system_.h (EXIT_MISMATCH): Define. - * src/main.c (main): Don't clear syntax table for version 1. - (usage): Document exit status. - * src/freeze.c (reload_frozen_state): Port GET_DIRECTIVE from the - branch, and require V directive to appear first in file. Fix - broken logic for detecting F and T in version 1 files. - -2006-07-22 Eric Blake - - * src/main.c (stackovf_handler): Document the problems in our - overflow handler. - * src/stackovf.c: Forward port changes in branch to use POSIX - sa_sigaction when available. - (process_sigsegv): Avoid buffer overrun when error string is - translated, although the fact that we translate in a signal - handler is still a bug. - * ltdl/m4/stackovf.m4 (M4_SYS_STACKOVF): Forward port changes - from branch to modernize checks. - - * modules/format.c (format): Avoid compiler warning that str may - be used uninitialized. - - * m4/m4private.h (DEBUG_MODULES, DEBUG_STKOVF) [DEBUG]: Fix - spelling. - (DEBUG_SYNTAX) [DEBUG]: Turn on more debug. - (DEBUG_MACRO): Remove unused macro. - * src/stackovf.c: Avoid compiler warnings. - * m4/input.c: Likewise. - * m4/module.c: Likewise. - * m4/output.c: Likewise. - * m4/path.c: Likewise. - * m4/symtab.c: Likewise. - * m4/syntax.c: Likewise. - -2006-07-20 Eric Blake - - * ltdl/m4/gnulib-cache.m4: gnulib-tool has changed again. - Regenerate to explicitly ask for --assume-autoconf=2.60. - -2006-07-19 Eric Blake - - * po/ChangeLog: Merge into main ChangeLog, then delete file. - * THANKS: Update. - - * doc/m4.texinfo (copying): Relax restriction on front-cover and - back-cover texts. - -2006-07-17 Eric Blake - - * configure.ac (AM_GNU_GETTEXT_VERSION): Bump requirement to - 0.14.5. - - * ltdl/m4/gnulib-cache.m4: Augment with `gnulib-tool --import - xvasprintf'. - * modules/format.c (includes): Use xvasprintf.h. - (format): Make static. Avoid buffer overflow, that can lead to - arbitrary code execution exploit. Only pass unsigned char to - is*(). Support F, g, and G specifiers. - * doc/m4.texinfo (Format): Expose buffer overrun bug. Document - new specifiers. - -2006-07-17 Gary V. Vaughan - - Ensure M4 compiles correctly with -DDEBUG, and use a single - consistent definition of various /DEBUG_[A-Z]+/ symbols: - - * m4/input.c: Have commented out out DEBUG_INPUT only by default. - (m4_print_token): Use m4_get_symbol_value_text and - m4_get_symbol_value_func calls instead of obsolescent VALUE_TEXT - and VALUE_FUNC respectively. - (m4__next_token): Use m4_print_token call instead of obsolescent - print_token symbol. - * m4/module.c: Have commented out out DEBUG_MODULE only by default. - * m4/output.c: Similarly for DEBUG_OUTPUT. - * m4/path.c: Similarly for DEBUG_INCL. - * m4/symtax.c: Similarly for DEBUG_SYM. - * m4/syntax.c: Similarly for DEBUG_SYNTAX. - * src/stackovf.c: Similarly for DEBUG_STACKOVF. - * m4/m4private.h (DEBUG): Add DEBUG_OUTPUT and DEBUG_STACKOVF to - preprocessor macros defined with -DDEBUG compiles. - -2006-07-17 Gary V. Vaughan (tiny change) - - * bootstrap: Correct typo in --download-po argument parsing. - -2006-07-15 Eric Blake - - * ltdl/m4/gnulib-cache.m4: Augment with `gnulib-tool --import - gendocs fdl'. - * tests/generate.awk (normalize): Recognize @tabchar. - * doc/m4.texinfo (Top): Start merging from branch. Remove tabs. - Fix menus. Upgrade FDL license from 1.1 to 1.2. Fix overfull - hboxes. - (Index macro, Shell commands, Incompatiblities): Rename nodes - from Index, UNIX commands, Other incompat. - (Platform macros, Using frozen files, Frozen file format 1) - (Frozen file format 2, Copying This Manual, Indices): New nodes. - * Makefile.am (EXTRA_DIST): Distribute gendocs. - (MAINTAINERCLEANFILES): Clean up files from gnulib. - (doc_m4_TEXINFOS): Depend on fdl.texi. - (web-manual): New maintainer target. - -2006-07-14 Gary V. Vaughan - - * doc/m4.texinfo (Modules): RMS asked me for an explanation of - the modular architecture of M4. The result is paraphrased here - for the benefit of future readers of the manual. - -2006-07-14 Gary V. Vaughan (tiny change) - - * Makefile.am (TESTSUITE_AT): Add missing tests/freeze.at. - -2006-07-14 Eric Blake - - * src/main.c (main): Avoid compiler warning. - * modules/gnu.c (renamesyms): Remove unused variable. - -2006-07-14 Gary V. Vaughan - - * m4/m4module.h (m4_regexp_syntax_decode, m4_regexp_syntax_encode) - (m4_get_regexp_syntax_opt, m4_set_regexp_syntax_opt): Declare - new functions for managing regexp syntax options. - * m4/m4private.h (m4): Add regexp_syntax field. - * m4/resyntax.c: New file implements the above. - * Makefile.am (m4_libm4_la_SOURCES): Add m4/resyntax.c. - * modules/gnu.c (RE_SYNTAX_BRE, RE_SYNTAX_ERE, builtin_eregexp) - (builtin_epatsubst, builtin_erenamsyms, m4_regexp_do) - (m4_patsubst_do, m4_renamesyms_do): Removed. - (builtin_changeresyntax): New builtin to change regular expression - syntax. - (m4_resyntax_encode_safe): Factor out diagnostics code. - * src/freeze.c (produce_resyntax_dump): New function to dump - default regexp syntax specifier to frozen file. - (reload_frozen_state): Updated to action 'R' directive. - * src/main.c (usage): Describe new -r option. - (long_options, OPTSTRING): Declare it. - (main): Encode and store cli regexp syntax option argument. - * tests/freeze.at (regexp syntax): New test that regexp syntax - survives freezing. - * tests/generate.awk (m4_pattern_allow): Updated for renamesyms. - * doc/m4.texinfo (Erenamesyms and Renamesyms, Eregexp and Regexp) - (Epatsubst and Patsubst): Renamed to... - (Renamesyms, Regexp, Patsubst): ...these respectively. Updated - documentation and added new examples. - (Changeresyntax): New section describing changeresyntax builtin, - and regexp syntax names. - (Regular expression syntax): New section describing differences - between various regular expression syntaxes. - (Frozen files): Document 'R' directive. - * NEWS: Updated. - -2006-07-13 Gary V. Vaughan - - * bootstrap: Enhanced to work more like our other scripts: - Add a copyright statement; support --version and --help; accept a - --download-po option with argument as a substitute for DOWNLOAD_PO - in the environment. - -2006-07-11 Eric Blake - - * Makefile.am (doc/m4.1): Port patch from branch that avoids - intermediate file. - * ltdl/m4/gnulib-cache.m4: Regenerate since upstream gnulib-tool - changed. - -2006-07-10 Gary V. Vaughan (tiny change) - - * tests/builtin.at (patsubst, regexp): Adjust these tests, now - that `\0' is no longer accepted. - - * src/main.c (usage): Alphabetize options within their sections. - - * modules/gnu.c (m4_regexp_search, regsub, substitute) - (esyscmd): Improve comments. - - * modules/gnu.c (substitute): Remove old warning for \0. - (substitute_warned): No longer required. Removed. - - * modules/gnu.c: Put macro definitions into alphabetical order. - -2006-07-07 Eric Blake - - * tests/freeze.at (loading format 1): New file, with new test. - * tests/testsuite.at: Include it. - * tests/macros.at (Arity, defn, and freeze): Add frozen keyword. - * tests/modules.at (Freezing modules): Likewise. - - * configure.ac (AC_PREREQ): Autoconf 2.60 is now out. - (AC_CHECK_HEADERS): Assume signal.h. - (AC_CHECK_HEADERS_ONCE): Use new feature to shrink configure. - (AC_CHECK_FUNCS_ONCE): Likewise. - * src/m4.h (includes): Assume signal.h. - -2006-07-05 Eric Blake - - Fix all testsuite failures on cygwin. - * doc/m4.texinfo (Syscmd, Esyscmd): Forward-port updates from - branch-1_4. Solves testsuite failure when uninstalled m4 is - shadowed by redefinition of PATH in libtool wrapper. - * Makefile.am (module_ldflags): Don't forget AM_LDFLAGS, which - contains the -no-undefined required by cygwin. - (TESTS_ENVIRONMENT): Export abs_top_builddir. - * tests/others.at (misc): Port to platforms where /etc/passwd - does not exist or does not contain user named root. - * tests/modules.at (AT_CHECK_M4_MODTEST): Look in correct - directory. - * tests/builtins.at (define, divert): Avoid overquoting. - * tests/generate.awk (new_group): Likewise. - -2006-07-05 Gary V. Vaughan - - The regs_allocated field in a struct re_pattern_buffer refers - to the state of a particular re_registers struct when used in - successive matches using the same compiled pattern. Avoid a - SEGV in `renamesyms' resulting from using a new re_registers - with an existing re_pattern_buffer: - - * modules/gnu.c (m4_pattern_buffer): Wrapper struct for associated - pattern buffer and registers. - (m4_regexp_search): New function to call re_regexp_search with - correctly matched pattern buffer and register instantiations. - (m4_regexp_compile): Return an m4_pattern_buffer. Adust all - callers. - -2006-07-04 Gary V. Vaughan - - * ltdl/m4/m4-getopt.m4 (M4_GETOPT): Update to take into account - changes to gnulib getopt.m4 since last build. - * Makefile.am (src_m4_SOURCES): Only compile shipped getopt module - if the system getopt fails M4_GETOPT tests. - -2006-06-22 Eric Blake - - * Makefile.am (EXTRA_DIST): Distribute gnulib-cache.m4. - Reported by Bruno Haible. - -2006-06-22 Ralf Wildenhues - - * m4/module.c (m4__module_exit): Avoid ltdl memory leak. - -2006-06-19 Eric Blake - - * THANKS: Update. - -2006-06-19 Ralf Wildenhues - - * Makefile.am (src_m4_DEPENDENCIES): Make dependency explicit. - (clean-local): Split into and depend upon... - (clean-local-tests, clean-local-src): ...these two. The latter - removes the libtool object directory below `src', to work around - a buglet in Automake, failing to list it. - (EXTRA_DIST): Distribute modules/perl.c. - -2006-06-19 Eric Blake - - * Makefile.am ($(srcdir)/doc/m4.1): No need to list $(srcdir) in - right side of dependency; VPATH does that. - (stamp-vcl): Update to use libtool's algorithm. - (EXTRA_DIST): Distribute stamp-vcl. - Reported by Ralf Wildenhues. - (TESTSUITE): Revert earlier change that used absolute path, as - that broke 'make dist' in VPATH. Stick with $(srcdir) instead. - (EXTRA_DIST): Revert earlier change of $(TESTSUITE). - (TESTS_ENVIRONMENT) [USE_GMP]: Revert earlier addition, since - atlocal takes care of it instead. - (check-local, installcheck-local, clean-local): Inline absolute - path to testsuite here, rather than relative path to testsuite - elsewhere. - -2006-06-19 Ralf Wildenhues - - * m4/m4private.h (DELETE): Cast away const here... - * src/stackovf.c (stackovf_exit): ...to avoid cast-as-lvalue here. - * src/freeze.c (reload_frozen_state): Avoid uninitialized - variable warning. - -2006-06-19 Eric Blake - - * Makefile.am (doc/m4.1): Build in $(srcdir), to match where - .info pages are built. - Reported by Ralf Wildenhues. - (EXTRA_DIST): Inline definition of testsuite, so that make dist - works again. - -2006-06-16 Eric Blake - - Follow recommendations from autoconf manual for autotest. - * Makefile.am (TESTSUITE): Factor the $(srcdir) out of uses, and - turn it into an absolute path until autotest provides an option - that allows us to avoid changing directories. Properly quote - throughout. - (TESTS_ENVIRONMENT) [USE_GMP]: Inform testsuite about GMP. - (check-recursive): Delete unused target. - ($(TESTSUITE)): Atomically update testsuite. - (CD_TESTDIR): Simplify. - (m4__cd): Delete unused macro. - (check-local): Let TESTSUITEFLAGS influence the run. - (installcheck-local): Let TESTSUITEFLAGS override - AUTOTEST_PATH. Add dependencies. - (clean-local): Clean up. - (DISTCLEANFILES, MAINTAINERCLEANFILES): Add directory location. - * README: Document how to use the testsuite. - -2006-06-15 Eric Blake - - * configure.ac (M4_DEFAULT_PRELOAD): Fix typo in last commit. - - * ltdl/m4/m4-error.m4 (M4_ERROR): Use M4_ instead of m4_ to avoid - clashes with m4sugar. - * ltdl/m4/m4-getopt.m4 (M4_GETOPT): Likewise. - * ltdl/m4/m4-gettext.m4 (M4_GNU_GETTEXT): Likewise. - * ltdl/m4/m4-obstack.m4 (M4_OBSTACK): Likewise. - * ltdl/m4/m4-regex.m4 (M4_REGEX): Likewise. - * ltdl/m4/gmp.m4 (_M4_LIB_GMP): Likewise. - * ltdl/m4/stackovf.m4 (M4_SYS_STACKOVF): Likewise. - * ltdl/m4/debug.m4 (M4_CHECK_DEBUGGING): Likewise. - * configure.ac: Likewise. - (M4_DEFAULT_PRELOAD): Use as a macro, not shell variable. - * Makefile.am (src_m4_CPPFLAGS): Use STACKOVF as a makefile - conditional. - * ltdl/m4/m4-gnulib.m4: Delete, no longer needed. - - Reduce compiler warnings. Inside GMP, mpq_t is an array type, so - const mpq_t is not assignable from plain mpq_t. Avoid - type-punning warnings caused trying to mix these types. - * modules/mpeval.c (numb_ior, numb_eor, numb_and, numb_lshift), - (numb_rshift, numb_divide, numb_modulo): Remove const qualifier. - * modules/evalparse.c (or_term, xor_term, and_term, shift_term), - (mult_term, exp_term): Remove type-punning casts. - (numb_pow): Remove const qualifier. - * src/freeze.c (reload_frozen_state): Fix typo in messages. - Fix variables that can be used uninitialized, which fixes - security hole where malicious frozen file can execute arbitrary - code. - -2006-06-14 Ralf Wildenhues - - * Makefile.am (modules_mpeval_la_LIBADD): Readd $(LIBADD_GMP). - -2006-06-13 Ralf Wildenhues - and Eric Blake - - Allow `make dist' to work again. - * Makefile.am (EXTRA_DIST): doc/helptoman.pl is gone. - (MAINTAINERCLEANFILES): Avoid redundant mention of dist_man_MANS. - (cvs-dist): Fix typo. - * NEWS: Match current version number. - -2006-06-13 Ralf Wildenhues - - * Makefile.am (AM_CPPFLAGS): Add $(LTDLINCL), so the right - ltdl.h is used. - - * bootstrap: Do not run libtoolize manually, this is done - correctly by autoreconf. Invoke autoreconf with --no-recursive - to avoid unnecessary rerunning of autotools for libltdl. - -2006-06-13 Eric Blake - - * THANKS: Update. - -2006-06-12 Eric Blake - - * m4/output.c [HAVE_MKTEMP]: Gnulib provides mkstemp, so don't - bother with mktemp. - * src/m4.h: Don't declare mktemp. - * m4/input.c (m4__next_token): Avoid bzero. - * configure.ac (AC_CHECK_FUNCS): Remove obsolete checks. - * Makefile.am (doc/m4.1): Depend on installed help2man, rather - than distributing outdated helptoman.pl. - * doc/helptoman.pl: Delete. - -2006-06-10 Eric Blake - - * README (Patches): Document the current dependence on CVS - builds of autotools. - * ltdl/m4/gnulib-cache.m4: Update, and use --macro-prefix=M4. - * configure.ac: Use consistent quoting throughout. - (AC_PREREQ): Bump to 2.59d. - (AC_INIT): Package name begins with uppercase. - (AC_ARG_WITH): Use AS_HELP_STRING. - (AM_INIT_AUTOMAKE): Enable gnits mode. - (AC_ISC_POSIX, AM_PROG_CC_STDC, AC_PROG_INSTALL, AC_PROG_MAKE_SET), - (AC_PROG_AWK, AM_C_PROTOTYPES, AC_C_CONST, AC_HEADER_STDC), - (AC_CHECK_HEADERS, AC_FUNC_ALLOCA, AC_FUNC_VPRINTF): Remove checks - done by gnulib or automake, or which autoconf has declared - obsolete. - * m4/m4private.h (Includes): Assume C89 or better, and use errno - unconditionally. - * m4/output.c (Includes): Likewise. - * modules/gnu.c (Includes): Likewise. - * modules/m4.c (Includes): Likewise. - * src/m4.h (Includes): Likewise. - - * README-alpha: Update web address. - * README: Likewise. Change encoding to ASCII. Remove old advice - about cygwin. Document bootstrapping dependency. - * AUTHORS: Update from branch-1_4. - * THANKS: Likewise. Change encoding to UTF-8. - * BACKLOG: Delete. This file is too old and unmaintained to be - worthwhile. - * ChangeLog: Change encoding to UTF-8. - - Avoid compiler warnings. - * m4/macro.c (trace_format): Don't mark this as a printf format, - since we don't accept the same set of modifiers as printf. It - would be nice if gcc let us specify a custom format archetype. - * src/main.c (main): Cast away const. - -2006-06-10 Andreas Schwab (tiny change) - Eric Blake - - * modules/time.c (ctime): Pass correctly typed variable to - m4_numeric_arg. - (gmtime): Likewise. - (localtime): Likewise. - (strftime): Likewise. - * m4/utility.c (m4_numeric_arg): For now, document arbitrary - limit inherent in this interface. - -2006-05-08 Bruno Haible (tiny change) - - * modules/m4.c (WEXITSTATUS): Provide fallback definition. - (sysval): Use WEXITSTATUS. - * modules/gnu.c (esyscmd): Set sysval to 0xffff, to accomodate both - big-endian and little-endian wait status definitions. - -2006-05-06 Eric Blake - - * po/Makevars (MSGID_BUGS_ADDRESS): Add. - * po/POTFILES.in (src/getopt.c, src/version-etc.c): These files live - in src, not gnu. - -2006-05-06 Eric Blake - - * configure.ac (LT_CONFIG_LTDL_DIR): Inform libtool which - subdirectory to use. - (support for -pipe): Move after LT_INIT, since it relies on - libtool internals. - -2006-05-05 Eric Blake - - * Makefile.am (doc/m4.1): Use $@, not $(srcdir)/doc/$@. - - * THANKS: Update. - -2006-05-05 Bruno Haible - and Eric Blake - - * configure.ac (gl_SOURCE_BASE, gl_M4_BASE, gl_MODULES): Move to... - * ltdl/m4/gnulib-cache.m4: ...this new file, per new gnulib-tool - usage pattern. - * bootstrap: Update usage of gnulib-tool. - -2006-05-04 Eric Blake - - * Makefile.am (doc/m4.1): Use EXEEXT on built binary. - Cleanup whitespace. - -2005-12-05 Gary V. Vaughan - - * bootstrap (func_update_po): Synch with CVS GNU tar. wget 1.9.x - and 1.10.x support --cache=off, so $WGETFLAGS are not necessary. - Reported by Eric Blake - -2005-12-04 Gary V. Vaughan - - * bootstrap (func_update_po): Test and set $WGETFLAGS to disable - http caching as -C is no longer supported by wget 1.10.x. - Reported by Eric Blake - -2005-10-20 Gary V. Vaughan - - * m4/module.c (caller_id): To match libtool-2.0 interface, changed - to ... - (iface_id): ...an lt_dlinterface_id type. - (m4__module_find): New abstraction for lt_dlhandle_fetch. Use - throughout, instead of calling obsolete lt_dlhandle_find directly. - (m4__module_next): Use multiloader-safe lt_dlhandle_iterate. Use - throughout, instead of calling obsolete lt_dlhandle_next. - * m4/m4private.h (m4__module_find): Declare it. - * m4/builtin.c (m4_builtin_find_by_name, m4_builtin_find_by_func): - Use m4__module_next instead of obsolete lt_dlhandle_next. - -2005-10-20 Gary V. Vaughan - - * bootstrap (func_update_po): Update pofiles directly from the - translation project. - * po/LINGUAS, po/cs.po, po/de.po, po/el.po, po/fr.po, po/it.po, - po/ja.po, po/nl.po, po/pl.po, po/ru.po, po/sv.po: No need to store - these files under source control anymore. - Suggested by Eric Blake - -2005-07-07 Paul Eggert - - * ltdl/m4/m4-gnulib.m4: Update FSF contact address. Somehow this - file escaped the address updates on 2005-05-01. - -2005-07-07 Gary V. Vaughan - - * bootstrap: Allow user overriding of gnulib-tool location, and - correctly determine module source directories whether gnulib-tool - is given as a relative or absolute path, or is found by searching - PATH. - Reported by Eric Blake - -2005-07-07 Ralf Wildenhues - - * ltdl/m4/debug.m4 (m4_CHECK_DEBUGGING): Make sure that both $rm - and $RM are defined for various versions of - AC_LIBTOOL_COMPILER_OPTION. - - * bootstrap (AUTORECONF): New variable to allow user overriding of - autoreconf path. - -2005-07-07 Gary V. Vaughan - - * doc/m4.texinfo (History): Add better notes on the ancestory of - GNU m4, and other historical interest. - -2005-05-08 Gary V. Vaughan - - * m4/symtab.c (m4_symbol_rename): New function that performs a low - level symbol rename. - * m4/m4module.h (m4_symbol_rename): Declare it as part of the API. - * modules/gnu.c (regsub): Factored out of m4_epatsubst_do... - (m4_patsubst_do, m4_renamesyms_do): ...wrappers that use - regsub... - (erenamesyms, renamesyms): ...builtins that use these to implement - macro renaming by regular expression. - * doc/m4.texinfo (Erenamesyms and Renamesyms): Document them. - * tests/generate.awk: Allow some forbidden `m4_' prefixed symbols - to stop the new generated tests from choking. - -2005-05-07 Gary V. Vaughan - - Since most of the build is handled from a single Makefile.am now, - we can teach make about the dependencies between the m4 binary and - the preopened modules it is built against: - - * configure.ac (PREOPEN_DEPENDENCIES): Substitute for a list of - preopened modules. - * Makefile.am (src_m4_DEPENDENCIES): Rebuild the m4 program if any - of the preopened modules have changed. - -2005-05-07 Gary V. Vaughan - - * configure.ac (gl_MODULES): Add mkstemp for machines that don't - have a native implementation. - -2005-05-06 Gary V. Vaughan - - * src/m4.h (EXIT_SUCCESS, EXIT_FAILURE): Removed. These are - handled already by gnu/exit.h. - - * configure.ac (gl_MODULES): Add assert to support a - --disable-assert configure time option for NDEBUG setting. - - * Makefile.am (src_m4_SOURCES): Add version-etc-fsf.c. - * bootstrap (src_modules): Add version-etc-fsf. - * src/main.c (version_etc_copyright): Removed. - - * ltdl/m4/m4-getopt.m4 (m4_GETOPT): Synch with gnulib/getopt.m4. - -2005-05-04 Gary V. Vaughan - - * src/m4.h (__CYGWIN__, WIN32): Canonicalise Windows and Cygwin - recognition macros. - * src/freeze.c (produce_frozen_state): Use \n line-endings even - on Windows, so that the frozen file reader will work. - Reported by Josef T. Burger - -2005-05-04 Vincent Lonngren - - Forward port of a patch that allowed m4-1.4.2 to compile on - QNX 6.3: - - * configure.ac (AC_CHECK_HEADERS): Add signal.h, - sys/signal.h. - * src/m4.h: And include them as appropriate. - * src/main.c, src/stackovf.h: Don't include signal.h literally; - m4.h will include the correct file. - -2005-05-04 Gary V. Vaughan - - * m4/m4private.h: Make errno visible for the sources patched - below. - -2005-05-04 Paul Eggert - - * src/main.c (print_program_name_CB): Preserve errno, since - M4ERROR relies on this. - * modules/gnu.c (m4_esyscmd): Clear errno before calling popen. - * modules/m4.c (m4_maketemp): Clear errno before calling mkstemp. - * m4/path.c (m4_path_search): Don't let "free" trash errno when - returning NULL. - - * m4/output.c (m4_insert_file): Don't assume errno has a valid - value simply because fread returns zero. This fixes a - portability bug reported by Marion Hakanson in - . - -2005-05-04 Santiago Vila - - * tests/stackovf.test: Use tempfile if available. - -2005-05-04 Robert Bihlmeyer (tiny change) - - http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=92629 - * m4/output.c (m4_insert_file): Do not mix buffered and - unbuffered I/O, as this breaks on the Hurd. - -2005-05-04 Gary V. Vaughan - - Gnulib has changed again. Reimport. Adjust. Rinse. Repeat. - Automake and Libtool now agree on subdir-objects and LTLIBOBJS, - and libtoolize does a better job of ltdl importing now too, so - take advantage of that while updating the tree: - - * acm4, config: Moved from here... - * ltdl/m4, ltdl/config: ...to here. - * doc/Makefile.am, m4/Makefile.am, modules/Makefile.am, - src/Makefile.am, tests/Makefile.am: Removed... - * Makefile.am: ...and migrated to here, with adjustments to - compensate for relative path differences. - * commit: Adjust relative paths. - * configure.ac: Adjust relative paths. - (AC_PREREQ): 2.59 isn't strictly new enough, we also need a - patch. - (LT_PREREQ): 2.0 isn't released yet, but will work when it is! In - the meanwhile, CVS HEAD libtool is needed. - (AM_INIT_AUTOMAKE): Added subdir-objects declaration. 1.9.5 isn't - stricly new enough, we also need a patch. - (AM_PROG_CC_C_O): Required for subdir-objects in Automake. - (AC_WITH_LTDL): Replaced with LT_WITH_LTDL. - (gl_MODULES): Don't list getopt and version-etc, as they don't - belong in libm4. - * bootstrap: After running gnulib-tool to import the listed - modules, fetch getopt and version-etc into src manually. - (ltdldir): Change to ltdl. - * src/main.c: Adjust for changes in version-etc API. - * ltdl/m4/m4-getopt.m4: New macro to mirror gnulib's getopt.m4, - but works when the getopt module isn't to be included in the lib. - * README: Add note about patching autoconf and automake to - bootstrap CVS m4. - -2005-05-02 Matt Kraai (tiny change) - - http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=84416 - * doc/m4.texinfo (Maketemp): Change maketemp to refer to a new, - empty file rather than to a nonexistent file. This closes a - common security hole. - * modules/m4.c (m4_maketemp): Implement the above, by using - mkstemp rather than mktemp. - -2005-05-01 Gary V. Vaughan - - The FSF are moving offices today. Changed their contact address - in all files from `59 Temple Place, Suite 330, MA 02111-1307' to - `51 Franklin Street, Fifth Floor, MA 02110-1301'. - -2005-03-11 Ralf Wildenhues (tiny change) - - * tests/Makefile (clean-local): Ignore testsuite cleanup - failures. - -2005-03-11 Per Bothner (tiny change) - - * tests/Makefile (clean-local): Only run the testsuite cleanup - if the testsuite has been generated. - -2005-02-11 Stepan Kasal - - * TODO: slight clarification of the example of qindir usage. - -2005-02-08 Gary V. Vaughan - - * TODO: Add qindir requirement, and defn bug. - From Stepan Kasal - -2005-02-08 Stepan Kasal - - * TODO: Add ``execution stack'', fix a typo. - * doc/m4.texinfo: Typos. - -2004-12-24 Eric Blake - - * configure.ac (INCLUDE_STDBOOL_H): Account for gnulib's move - to the gnu subdirectory. - * acm4/m4-error.m4 (INCLUDE_ERROR_H): Likewise. - * acm4/m4-obstack.m4 (INCLUDE_OBSTACK_H): Likewise. - * acm4/m4-regex.m4 (INCLUDE_REGEX_H): Likewise. - * m4/system_.h: Likewise, in non-configured includes. - -2004-10-14 Noah Misch , - Gary V. Vaughan - - * m4/m4.c (m4_context_field_table, m4_context_opt_bit_table): - Protect definitions from macro expansion under -DNDEBUG by - parenthesising the expanded function names. - * m4/syntax.c (m4_get_syntax_lquote, m4_get_syntax_rquote) - (m4_get_syntax_bcomm, m4_get_syntax_ecomm) - (m4_is_syntax_single_quotes, m4_is_syntax_single_comments) - (m4_is_syntax_macro_escaped): Similarly protect function - definitions from macro expansion under -DNDEBUG by #undefing the - matching macro names before each definition. Also, move all the - function definitions to the end of the file so that any - invocations in the rest of the file pick up the fast macro - versions. - * m4/m4private.h (m4_set_symbol_table, m4_set_syntax_table) - (m4_set_debug_file, m4_set_trace_messages) - (m4_set_warning_status_opt, m4_set_no_gnu_extensions_opt) - (m4_set_nesting_limit_opt, m4_set_debug_level_opt) - (m4_set_max_debug_arg_length_opt): New fast macro versions of the - option setter functions. - -2004-09-23 Gary V. Vaughan - - * po/POTFILES.in: Reflect move of gnulib files from gnulib/m4 - to gnu. - -2004-09-23 Gary V. Vaughan - - * src/main.c: Include gnulib files from the correct directory. - - * gnulib/*: Don't store any of the gnulib files in arch, as they - generate spurious changes. - * Makefile.am (ACLOCAL_AMFLAGS): Remove gnulib/acm4 since the - gnulib macros now share our macro directory. - (SUBDIRS): Descend into `gnu' rather than `gnulib'. - * bootstrap: Call gnulib-tool to import from the gnulib tree. - (gl_AC_HEADER_INT_TYPES_H, gl_AC_HEADER_STDINT_H, - gl_AC_TYPE_UINTMAX_T): Patch gnulib.m4 to define these in terms of - the gettext macros from autopoint that overwrite the gnulib-tool - imported versions. Import sources and Makefile.am into the `gnu' - directory. Changed all callers. - * configure.ac (gl_EARLY, gl_SOURCE_BASE, gl_M4_BASE, gl_MODULES, - gl_INIT): Call these gnulib-tool macros instead of the hardcoded - for imported modules. - * acm4/m4-error.m4, acm4/m4-gettext.m4, acm4/m4-obstack.m4, - acm4/m4-regex.m4: Use AC_BEFORE to enforce ordering rather than - hardcoding the gnulib macros they wrap. - -2004-07-15 Gary V. Vaughan - - Latest CVS libtool can preload modules in libraries, including - its own module loaders! Tweak m4 so that it doesn't try to treat - libltdl's module loaders as m4 modules when freezing and on exit: - - * gnulib/acm4/*.m4: Don't store these files in arch since they - generate spurious changes. - * bootstrap: Simplify initial libtoolize call, since CVS - libtoolize is smarter these days. - * doc/Makefile.am (%.1): Make the helptoman call work with a VPATH - build. - * m4/module.h (m4__module_exit): Missing declaration. - * m4/m4private.h (m4__module_next): New function declaration. - * m4/module.c (m4__module_next): lt_dlhandle_{firs,nex}t - encapsulation. Changed all callers. - (m4__module_interface): New function to verify m4 loadable module - interfaces. - (m4__module_init): Register the interface validator. - (m4__module_exit): Only close my own modules. - * modules/m4.c (unistd.h): Provide missing declaration. - (m4_set_sysval, m4_sysval_flush, m4_dump_symbols) - (m4_expand_ranges): More missing declarations. - * modules/modtest.c (export_test): Ditto. - * src/Makefile.am (AM_CPPFLAGS): Add libltdl directory. - * src/main.c (main): Bump copyright year. - * tests/modules.at: Fix sed syntax error. - - -2004-06-17 Gary V. Vaughan - - Tweaking to enable compilation with latest CVS libtool and - libltdl. We can't just dump the library files directly into the - m4 directory anymore now that libltdl is built from pieces itself: - - * bootstrap: Rewritten to use latest libtoolize sanely, and to - set up libltdl subdirectory. - * configure.ac (AC_CONFIG_AUX_DIR): Point to our own, not the - gnulib subdirectory's config. - (TIMESTAMP): Use $ac_aux_dir for VPATH builds. - (m4_pattern_forbid): Remove the cruft to deal with renamed jm_ - macros from gnulib. - (AC_LIB_LTDL): Latest libltdl is a sub-project with its own - configure.ac, so use AC_WITH_LTDL instead. - * Makefile.am (SUBDIRS): Add libltdl. - * acm4/m4-regex.m4 (jm_INCLUDED_REGEX): Updated. gnulib now uses - gl_INCLUDED_REGEX. - * m4/Makefile.am (AM_CPPFLAGS): Add INCLTDL. - (libm4_la_SOURCES): Remove ltdl.c and ltdl.h. - (libm4_la_LIBADD): Add LIBLTDL. - * m4/ltdl.c, m4/ltdl.h: Removed. - * m4/m4module.h: Include canonical ltdl.h. - * po/*.po: Updated. - -2004-06-14 Gary V. Vaughan - - * gnulib/import: Now updates makefile fragments, and configure.ac. - * gnulib/m4/gnulib.am: New file. Generated makefile fragments. - * gnulib/m4/Makefile.am: include it. - * gnulib/acm4/intmax.m4, gnulib/acm4/longdouble.m4, - gnulib/acm4/longlong.m4, gnulib/acm4/printf-posix.m4, - gnulib/acm4/signed.m4, gnulib/acm4/size_max.m4, - gnulib/acm4/wchar_t.m4, gnulib/acm4/wint_t.m4, - gnulib/acm4/xsize.m4: New macro files from latest gnulib import. - * gnulib/acm4/alloca.m4, gnulib/acm4/inttypes_h.m4, - gnulib/acm4/lib-ld.m4, gnulib/acm4/lib-prefix.m4, - gnulib/acm4/error.m4, gnulib/acm4/po.m4, gnulib/acm4/regex.m4, - gnulib/acm4/stdbool.m4, gnulib/acm4/stdint_h.m4, - gnulib/acm4/uintmax_t.m4, gnulib/acm4/ulonglong.m4, - gnulib/acm4/unlocked-io.m4, gnulib/acm4/xalloc.m4, - gnulib/acm4/free.m4, gnulib/acm4/gettext.m4, - gnulib/acm4/glibc21.m4: Updated macro files from latest gnulib - import. - * gnulib/m4/getopt_int.h: New source file from latest gnulib - import. - * gnulib/m4/alloca.c, gnulib/m4/alloca_.h, gnulib/m4/getopt1.c, - gnulib/m4/obstack.c, gnulib/m4/obstack.h, gnulib/m4/regex.c, - gnulib/m4/unlocked-io.h, gnulib/m4/version-etc.c, - gnulib/m4/xmalloc.c, gnulib/m4/getopt.c, gnulib/m4/getopt.h: - Updated source files from latest gnulib. - -2004-02-29 Gary V. Vaughan - - * config/mailnotify: New file for mailing commit notifications, - imported from cvs-utils. - * commit: Updated from cvs-utils and tweaked for m4. - -2003-12-01 Gary V. Vaughan - - * config/mkstamp: Updated from CVS libtool. - * configure.ac: Generate a gnu coding standards compliant version - number, and use it for the banner. - * Makefile.am (stamp-vcl): New rules to force m4 to be regenerated - mhen the TIMESTAMP changes in ChangeLog, but the file modification - time doesn't (e.g. in cvs commit). Otherwise dist tarballs will - contain the previous version number. - * src/main.c: Make --version output conform to the GNU standard. - - * configure.ac (AM_INIT_AUTOMAKE): Require 1.7g... - * modules/Makefile.am (gnu_la_SOURCES, load_la_SOURCES, - m4_la_SOURCES, traditional_la_SOURCES, modtest_la_SOURCES, - shadow_la_SOURCES, import_la_SOURCES, stdlib_la_SOURCES, - time_la_SOURCES): ...so that these are defaulted correctly, and - can be removed from this file. - (AM_LDFLAGS): Add -module... - (gnu_la_LDFLAGS, load_la_LDFLAGS, m4_la_LDFLAGS, - traditional_la_LDFLAGS, modtest_la_LDFLAGS, shadow_la_LDFLAGS, - import_la_LDFLAGS, stdlib_la_LDFLAGS, time_la_LDFLAGS): ...so that - the individual settings can be removed. - * m4/Makefile.am (libm4_la_LIBADD): Add $(LTLIBINTL) here once... - * module/Makefile.am (gnu_la_LIBADD, load_la_LIBADD, - m4_la_LIBADD, traditional_la_LIBADD, modtest_la_LIBADD, - shadow_la_LIBADD, import_la_LIBADD, stdlib_la_LIBADD, - time_la_LIBADD): ...so that these are picked up as a deplib of - libm4 and don't need to be set explicitly. - -2003-11-18 Gary V. Vaughan - - * modules/Makefile.am (pkglibexec_LTLIBRARIES): Remove perl.la - from the standard build. It is too fragile. - - * gnulib/acm4/libtool.m4, m4/ltdl.c, m4/ltdl.h: Reimported from - CVS libtool after merging m4 changes across to libtool. - - * m4/symtab.c (m4_symtab_create): Fix a careless use of sizeof. - * m4/path.c (search_path_add): Ditto. - -2003-11-13 Gary V. Vaughan - - * configure.ac (AC_LIBTOOL_TAGS): Don't include shell code for - libtool tags we don't use in configure. This reduces the size - of the script from over 1Mb to under 700Kb. - -2003-11-13 Gary V. Vaughan - - The import script was not written properly, and the last gnulib - import was incomplete. Fixed that problem, and reimport our - gnulib dependencies, which picks up the address calculation - overflow checks described by Paul below. Also tweak the clients - of the gnulib xalloc module not to use deprecated macros: - - * gnulib/import: Recurse through module dependencies rather than - naively descending only one level. - * configure.ac: Add calls to gnulib's strnlen and extension module - macros. - * gnulib/m4/Makefile.am: Add snippets from gnulib's strnlen and - extension modules. - * gnulib/acm4/extensions.m4, gnulib/acm4/xalloc.m4, - gnulib/m4/alloca.c, gnulib/m4/obstack.c, gnulib/m4/obstack.h, - gnulib/m4/stdbool_.h, gnulib/m4/unlocked-io.h, gnulib/m4/xalloc.h, - gnulib/m4/xmalloc.c, gnulib/m4/xstrdup.c: Updated from CVS - gnulib. - * gnulib/acm4/libtool.m4: Updated from CVS libtool. - * m4/hash.c (m4_get_hash_iterator_next): Use `xzalloc (S)' in - place of `xcalloc (1, S)'. - * m4/m4.c (m4_create): Likewise. - * m4/m4private.h (m4_symbol_value_create): Likewise. - * m4/symtab.c (symtab_fetch): Likewise. - * m4/syntax.c (m4_syntax_create): Likewise. - * src/freeze.c (reload_frozen_state): Likewise. - * m4/path.c (search_path_add): Eliminate use of deprecated NEW - macro. - * m4/symtab.c (m4_symtab_create): Likewise. - -2003-11-13 Gary V. Vaughan - - * tests/module.at: Comment typo. - -2003-10-10 Gary V. Vaughan - - * tests/modules.at (modules: importing): Apply some lateral - thinking, and use AT_CHECK to compare the output of a sed pass - over stderr against the canonical strerror string. - - * tests/modules.at (modules: importing): Edit the generated stderr - output to canonicalize strerror output, before a comparison. - -2003-10-10 Gary V. Vaughan - - Tru64UNIX perl is sloppy with namespace pollution. This patch is - careful not to trip over the mess: - - * modules/perl.c: Some builds of perl install headers that contain - `#define try __builtin_try'. Be sure to undefine that macro - before `m4/hash.h' gets included, which uses the `try' symbol. - * m4/system_.h: Similarly for `bool'. Undefine `bool', `true' and - `false' before including `stdbool.h'. - (DELETE): This symbol is not in m4's namespace, and is in any - case only used internally... - * m4/m4private.h (DELETE): ...so move it to here. - Reported by Martin MOKREJS - -2003-10-08 Paul Eggert - - Don't use XMALLOC and XCALLOC. Once we install the - corresponding patch into gnulib, this will fix some - address-calculation overflow bugs on hosts where calloc (A, B) - returns garbage when A*B overflows. - - * m4/hash.c (m4_hash_new, node_new, m4_hash_resize, - maybe_grow, m4_get_hash_iterator_next): Replace XMALLOC with - xmalloc, XCALLOC with xcalloc. - * m4/m4.c (m4_create): Likewise. - * m4/m4private.h (m4_symbol_value_create): Likewise. - * m4/output.c (m4_output_init): Likewise. - * m4/symtab.c (symtab_fetch, m4_set_symbol_traced): Likewise. - * m4/syntax.c (remove_syntax_attribute): Likewise. - * src/freeze.c (reload_frozen_state): Likewise. - * src/main.c (main): Likewise. - -2003-10-07 Gary V. Vaughan - - * Makefile.am (ACLOCAL_AMFLAGS): Search in the new acm4 and - gnulib/acm4 directories for aclocal m4 macros. - * gnulib/Makefile.am (EXTRA_DIST): Removed. - (MAINTAINERCLEANFILES): Add Makefile.in. - * configure.ac (m4_GNULIB_MODULES): Use it to declare which gnulib - modules we use. - * acm4/m4-gnulib.m4 (m4_GNULIB_MODULES): New macro. - * gnulib/import: New file. Temporary script for updating gnulib - imported files, until gnulib-tool is working. - * gnulib/config/codeset.m4, gnulib/config/error.m4, - gnulib/config/exitfail.m4, gnulib/config/extensions.m4, - gnulib/config/getopt.m4, gnulib/config/gettext.m4, - gnulib/config/glibc21.m4, gnulib/config/iconv.m4, - gnulib/config/intdiv0.m4, gnulib/config/inttypes-pri.m4, - gnulib/config/inttypes.m4, gnulib/config/inttypes_h.m4, - gnulib/config/isc-posix.m4, gnulib/config/lcmessage.m4, - gnulib/config/lib-ld.m4, gnulib/config/lib-link.m4, - gnulib/config/lib-prefix.m4, gnulib/config/malloc.m4, - gnulib/config/nls.m4, gnulib/config/obstack.m4, - gnulib/config/onceonly_2_57.m4, gnulib/config/po.m4, - gnulib/config/progtest.m4, gnulib/config/realloc.m4, - gnulib/config/regex.m4, gnulib/config/restrict.m4. - gnulib/config/stdbool.m4, gnulib/config/stdint_h.m4, - gnulib/config/strerror_r.m4, gnulib/config/strndup.m4, - gnulib/config/strnlen.m4, gnulib/config/strtol.m4, - gnulib/config/uintmax_t.m4, gnulib/config/ulonglong.m4, - gnulib/config/unlocked-io.m4, gnulib/config/xalloc.m4, - gnulib/config/xstrndup.m4: Removed. - * gnulib/acm4/alloca.m4, gnulib/acm4/codeset.m4, - gnulib/acm4/error.m4, gnulib/acm4/exitfail.m4, - gnulib/acm4/extensions.m4, gnulib/acm4/free.m4, - gnulib/acm4/getopt.m4, gnulib/acm4/gettext.m4, - gnulib/acm4/glibc21.m4, gnulib/acm4/iconv.m4, - gnulib/acm4/intdiv0.m4, gnulib/acm4/inttypes-pri.m4, - gnulib/acm4/inttypes.m4, gnulib/acm4/inttypes_h.m4, - gnulib/acm4/isc-posix.m4, gnulib/acm4/lcmessage.m4, - gnulib/acm4/lib-ld.m4, gnulib/acm4/lib-link.m4, - gnulib/acm4/lib-prefix.m4, gnulib/acm4/malloc.m4, - gnulib/acm4/nls.m4, gnulib/acm4/obstack.m4, - gnulib/acm4/onceonly_2_57.m4, gnulib/acm4/po.m4, - gnulib/acm4/progtest.m4, gnulib/acm4/realloc.m4, - gnulib/acm4/regex.m4, gnulib/acm4/restrict.m4. - gnulib/acm4/stdbool.m4, gnulib/acm4/stdint_h.m4, - gnulib/acm4/strerror_r.m4, gnulib/acm4/strndup.m4, - gnulib/acm4/strnlen.m4, gnulib/acm4/strtol.m4, - gnulib/acm4/uintmax_t.m4, gnulib/acm4/ulonglong.m4, - gnulib/acm4/unlocked-io.m4, gnulib/acm4/xalloc.m4, - gnulib/acm4/xstrndup.m4: Reimported from CVS gnulib with - gnulib/import script. - * gnulib/m4/alloca.c, gnulib/m4/alloca_.h, gnulib/m4/error.c, - gnulib/m4/error.h, gnulib/m4/exitfail.c, gnulib/m4/free.c, - gnulib/m4/malloc.c, gnulib/m4/obstack.c, gnulib/m4/obstack.h, - gnulib/m4/realloc.c, gnulib/m4/regex.c, gnulib/m4/strtol.c, - gnulib/m4/version-etc.c, gnulib/m4/version-etc.h, - gnulib/m4/xalloc.h, gnulib/m4/xmalloc.c: Updated from CVS - gnulib with gnulib/import script. - * configure.ac, gnulib/m4/Makefile.am: Manually insert anticipated - guards ready for gnulib-tool to autoupdate on import. - * config/debug.m4, config/gmp.m4, config/m4-error.m4, - config/m4-gettext.m4, config/m4-obstack.m4, config/m4-regex.m4, - config/stackovf.m4: Moved from here... - * acm4/debug.m4, acm4/gmp.m4, acm4/m4-error.m4, - acm4/m4-gettext.m4, acm4/m4-obstack.m4, acm4/m4-regex.m4, - acm4/stackovf.m4: ...to here, to separate aclocal macros from - configure time helper scripts. - * config/error.m4: Removed; superceded by gnulib/acm4/error.m4. - * m4/hash.c, m4/m4.c, m4/macro.c, m4/module.c, m4/output.c, - m4/path.c, m4/symtab.c, m4/syntax, m4/system_.h, modules/m4.c, - src/main.c, src/stackovf.c: s/xfree/free/g to comply with new - gnulib xalloc.h. - * src/main.c (version_etc_copyright): Only output the current - year. - (version_etc): Call with new variadic API. - -2003-09-16 Gary V. Vaughan - - * gnulib/m4/version-etc.c, gnulib/m4/version-etc.h: Import - version-etc module from CVS gnulib. - * po/POTFILES.in: Add gnulib/m4/version-etc.c. - * src/Makefile.am: Build it. - * src/main.c: Use it. - - * gnulib/m4/exit.h: Import exit module from CVS gnulib. - * gnulib/m4/Makefile.am (pkginclude_HEADERS): Add exit.h. - * m4/system_.h: Don't define EXIT_SUCCESS and FAILURE, include - exit.h instead. - -2003-09-15 Charles Wilson , - Gary V. Vaughan - - * bootstrap: Separate options. - * configure.ac (AM_GNU_GETTEXT_VERSION): Bump to 0.12.1. - * gnulib/m4/Makefile.am (stdbool.h): Use srcdir, gnulib_srcdir is - not set. - * modules/Makefile.am (gnu_la_LIBADD, load_la_LIBADD) - (m4_la_LIBADD, mpeval_la_LIBADD, traditianal_la_LIBADD) - (modtest_la_LIBADD, import_la_LIBADD, perl_la_LIBADD) - (shadow_la_LIBADD, stdlib_la_LIBADD, time_la_LIBADD): Add - $(LTLIBINTL) for gettext support on cygwin. - * src/Makefile.am (m4_LDADD): Remove $(INTLLIBS), since we now - have $(LTLIBINTL) from the preloaded module la files. - * README: Remove the warning about using --disable-nls on Windows - machines. - -2003-09-15 Gary V. Vaughan - - * gnulib/m4/regex.c: s//"regex.h"/ or else the compiler - picks up the system regex.h if gl_REGEX decides gnulib/m4/regex.c - is required. - -2003-09-12 Gary V. Vaughan - - * doc/STYLE: Document the gnulib header naming conventions, and - #include policy. - * gnulib/m4/error_.h, gnulib/m4/gettext_.h, gnulib/m4/obstack_.h, - gnulib/m4/regex_.h: Renamed to gnulib/m4/error.h, - gnulib/m4/gettext.h, gnulib/m4/obstack.h, gnulib/m4/regex.h - respectively. - * gnulib/m4/Makefile.am: Remove the rules to build these headers. - - * gnulib/m4/strtol.c, gnulib/config/strtol.m4: Import strtol - module from CVS gnulib. - * configure.ac (AC_REPLACE_FUNCS): Remove strtol. - (gl_FUNC_STRTOL): In favour of the module macro. - -2003-09-12 Gary V. Vaughan - - Replace the getopt code with CVS gnulib getopt. The source files - detect whether they are in a glibc environment and preprocess away - all of the code if there is a system getopt, so we can compile - them into the m4 executable unconditionally: - - * gnulib/m4/getopt.c, gnulib/m4/getopt1.c, gnulib/m4/getopt.h, - gnulib/config/getopt.m4: Import getopt module from CVS gnulib. - * configure.ac (gl_GETOPT): Use this instead of homebrew inline - macros. - * src/getopt.c, src/getopt1.c, src/gnu-getopt.h: Removed old - version. - * src/Makefile.am: Adjust. - * src/main.c: Always include our shipped getopt.h. - * po/POTFILES.in: Use new location of getopt.c. - -2003-09-12 Gary V. Vaughan - - * configure.ac (AC_CONFIG_FILES): Remove config/Makefile. - * config/Makefile.am: Removed. Automake 1.8 distributes the files - in this directory automatically. - * Makefile.am (EXTRA_DIST): Except config/mkstamp. - - * configure.ac (pkglibexecdir): Don't try and set it here, PACKAGE - isn't set yet. - * m4/Makefile.am (MODULE_PATH): Removed. Calculate pkglibexecdir - inline. - * modules/Makefile.am (pkglibexecdir): Set it here. - (pkgmodincdir): Renamed to pkgmodincludedir). Changed all clients. - - * gnulib/m4/regex.c, gnulib/m4/regex_.h, gnulib/config/regex.m4: - Import regex module from CVS gnulib. - * gnulib/config/restrict.m4: Ditto for dependee module restrict. - * config/m4-regex.m4 (m4_REGEX): Wrap gnulib/config/regex.m4, but - do extra substitutions for Makefile. - * configure.ac: Use it. - * gnulib/m4/Makefile.am: Maybe install regex.h after linking it - from regex_.h if necessary. - * m4/system_.h: Include the correct version of regex.h. - * m4/regex.c, m4/regex.h, config/regex.m4: Removed legacy - version. - * po/POTFILES.in: Use new location of regex.c. - - * gnulib/m4/Makefile.am (EXTRA_DIST): Removed malloc.c and - realloc.c: automake distributes these files already. - -2003-09-12 Gary V. Vaughan - - Replace the xstrzdup code by importing the xstrndup module from - CVS gnulib, along with its dependencies: strndup and strnlen: - - * gnulib/m4/xstrndup.c, gnulib/m4/xstrndup.h, - gnulib/config/xstrndup.m4: Import xstrndup module from CVS - gnulib. - * gnulib/m4/strndup.c, gnulib/m4/strndup.h, - gnulib/config/strndup.m4: Ditto wrt strndup. - * gnulib/m4/strnlen.c, gnulib/config/strnlen.m4: Ditto wrt - strnlen. - * gnulib/m4/Makefile.am: Add rules from newly imported modules. - However, contrary to gnulib, we install xstrndup.h. - * configure.ac (AC_REPLACE_FUNCS): Remove xstrzdup. - * gnulib/lib/xstrzdup.c: Delete. This was never a gnulib file, it - is an artifact of the old m4 portability layer. - * configure.ac (gl_XSTRNDUP): This is the gnulib equivalent. - * m4/system_.h: Include xstrndup.h. - * m4/macro.c (process_macro): Call xstrndup, not xstrzdup. - -2003-09-11 Gary V. Vaughan - - Reimport the latest xalloc module from CVS gnulib, and adjust the - m4 sources to take advantage of xalloc xfree. Also create a new - macro DELETE with the same semantics as the old m4 XFREE macro, - and carefully tweak callers: - - * gnulib/config/xalloc.m4, gnulib/m4/xalloc.h: Updated from CVS - gnulib. - * m4/utility.c (xfree): Removed. This function is now supplied by - gnulib xalloc. - * m4/m4private.h (WITH_DMALLOC): Removed XFREE redefine. - * m4/path.c (search_path_add): Use NEW macro from xalloc.h. - * m4/symtab.c (m4_symtab_create): Ditto. - * m4/system_.h: Removed XFREE redefine. - (DELETE): New macro with same functionality as the original m4 - XFREE macro, but based on xalloc.h now. Changed all callers. - * src/main.c (main): Use XMALLOC macro. - * m4/hash.c, m4/macro.c, m4/symtab.c, m4/syntax.c: Use xfree - instead of XFREE. - * m4/output.c (m4_output_exit): Use DELETE instead of XFREE. - -2003-09-10 Gary V. Vaughan - - Import the xalloc module from CVS gnulib, along with its - dependencies: exitfail, malloc and realloc. We had different - semantics for our XFREE and a function xfree() not supplied by - gnulib, so also a bit of work to keep everything running - smoothly: - - * configure.ac (AC_REPLACE_FUNCS): Removed xmalloc and xstrdup. - (gl_XALLOC): Use gnulib equivalents. - * gnulib/config/exitfail.m4, gnulib/m4/exitfail.h, - gnulib/m4/exitfail.c: Import exitfail module from CVS gnulib. - * gnulib/config/malloc.m4, gnulib/m4/malloc.c: Ditto wrt malloc. - * gnulib/config/realloc.m4, gnulib/m4/realloc.c: Ditto wrt - realloc. - * gnulib/config/xalloc.m4, gnulib/m4/xalloc.h, - gnulib/m4/xmalloc.c, gnulib/m4/xstrdup.c: Ditto wrt xalloc. - * gnulib/m4/Makefile.am: Add fragment from gnulib for newly - imported modules. - (pkgincdir): Removed. Use pkgincludedir instead. - * m4/m4private.h (XFREE): xfree already checks for NULL. - * m4/system_.h: Use xalloc module, and remove macros already - supplied by xalloc.h. - * m4/utility.c (xfree): xalloc does not yet implement xfree, so - moved the old definition from m4/xmalloc.c to here for now. - -2003-09-09 Gary V. Vaughan - - Import the error and progname modules from CVS gnulib. Our old - error.c subsumed the functionality of both, so a little adjustment - was required to accomodate the split in sources. Also added more - wrapper macros to choose between a system installed error.h or our - shipped gnulib error module: - - * m4/error.c, m4/error.h: Removed. - * m4/Makefile.am: Adjust. - (pkgincdir): Removed. Use pkgincludedir instead. - * m4/module.h, src/main.c: Don't include `m4/error.h'. - * m4/system_.h (INCLUDE_ERROR_H): Add a substitution for suitable - error.h. - * gnulib/m4/progname.c: Imported from CVS gnulib. - * gnulib/m4/progname.h: Ditto. - * src/main.c: Adjust to use progname module. - * gnulib/m4/error.c: Imported from CVS gnulib. - * gnulib/m4/error_.h: Ditto. - * gnulib/m4/Makefile.am: Build the error module into our libgnu.la - if appropriate, and link a local error.h if the system version is - missing. - (libgnu_la_SOURCES) Add progname module sources. - * gnulib/config/error.m4: Imported from CVS gnulib. - * gnulib/config/strerror_r.m4: Ditto. - * config/m4-error.c: New file. Wrap gnulib error.m4 but arrange - to have ERROR_H for Makefile substitutions and tell system.h - whether the system error.h should be used, or a locally installed - version. - * configure.ac (jm_PREREQ_ERROR): Replaced by a call to m4_ERROR. - -2003-09-09 Gary V. Vaughan - - * gnulib/m4/Makefile.am (MOSTLYCLEANFILES): Typo - s/gettext_.h/gettext.h/. - - * bootstrap: Revert 2003-09-04 patch now that CVS autoconf and - automake have been fixed. - - * config/m4-obstack.m4 (m4_FUNC_OBSTACK): D'oh! Now that we wrap - gl_OBSTACK, which in turn calls AC_FUNC_OBSTACK, don't rerun bits - of code originally snarfed from AC_FUNC_OBSTACK!!! While I'm here - rename to m4_OBSTACK in light of wrapping gl_OBSTACK. - -2003-09-09 Gary V. Vaughan - - The gnulib obstack module requires the gnulib gettext module for - systems that do not have GNU gettext installed. Because we use - -Ignulib/m4 in our Makefiles it is not safe to drop gettext.h in - that directory incase it clashes with the system gettext.h. This - delta uses gettext_.h and extra rules in the Makefile to make a - link to gettext.h when needed: - - * Makefile.am (auxdir): Removed. No longer used. - * configure.ac (ac_aux_dir): Removed AC_SUBST. No longer used. - (TIMESTAMP): List path to `mkstamp' literally, as ac_aux_dir has - moved. - (AC_CONFIG_LIBOBJ_DIR): Declare this for possible future single - Makefile based build. - (AC_CONFIG_AUX_DIR): Now we use gnulib/config where the majority - of the macros are kept. - * Makefile.am (ACLOCAL_MFLAGS): Search gnulib/config first. - * configure.ac (AM_INIT_AUTOMAKE): Require 1.7a. - * config/Makefile (ACLOCAL_MACROS): Removed. Automake 1.7a - distributes these automatically. - * config/regex.m4 (jm_WITH_REGEX): Fixed underquoting to prevent - warning from automake-1.7a. - * config/debug.m4 (M4_AC_CHECK_DEBUGGING): Renamed to - m4_CHECK_DEBUGGING for consistency with gnulib prefixes. Changed - all callers. - * config/m4-obstack.m4 (M4_AC_FUNC_OBSTACK): Ditto - wrt. m4_FUNC_OBSTACK. - * config/stackovf.m4 (M4_AC_SYS_STACKOVF): Ditto - wrt. m4_sys_STACKOVF. - * config/gmp.m4 (_M4_AC_LIB_GMP, M4_AC_LIB_GMP): Ditto - wrt. _m4_LIB_GMP, m4_LIB_GMP. - (ac_gmp_save_LIBS, ac_cv_using_lib_gmp): Don't use autoconf's - namespace. Renamed to m4_gmp_save_LIBS and m4_cv_using_lib_gmp - respectively. - * config/m4-gettext.m4: New file to set GETTEXT_H appropriately. - * gnulib/m4/Makefile.am: Added a new block to make an appropriate - gettext.h link on deficient systems. - (pkginc_HEADERS): Mention $(GETTEXT_H). - (EXTRA_HEADERS): Mention gettext.h. - * gnulib/config/gettext_.h: New file from gnulib's gettext.h. - * gnulib/config/codeset.m4, gnulib/config/gettext.m4, - gnulib/config/glibc21.m4, gnulib/config/iconv.m4, - gnulib/config/intdiv.m4, gnulib/config/inttypes-pri.m4, - gnulib/config/inttypes.m4, gnulib/config/inttypes_h.m4, - gnulib/config/isc-posix.m4, gnulib/config/lcmessage.m4, - gnulib/config/lib-ld.m4, gnulib/config/lib-link.m4, - gnulib/config/lib-prefix.m4, gnulib/config/nls.m4, - gnulib/config/po.m4, gnulib/config/progtest.m4, - gnulib/config/stdint_h.m4, gnulib/config/uintmax_t.m4, - gnulib/config/ulonglong.m4: Imported from CVS gnulib. - -2003-09-05 Gary V. Vaughan - - We can't mirror the gnulib directory structure here, since we need - to be able to eg. `#include ' from our source files, - which is much easier if the local obstack.h is created in a - directory named m4. Rather than trying to symlink everything into - the m4 directory, now we build a libtool convenience library from - the sources we get from gnulib and link that with libm4.la: - - * gnulib/config/extensions.m4: Imported from CVS gnulib. - * gnulib/config/unlocked-io.m4: Ditto. - * gnulib/m4/unlocked-io.h: Ditto. - * gnulib/m4/obstack.m4, gnulib/m4/onceonly_2_57.m4, - gnulib/m4/stdbool.m4: All moved to gnulib/config directory. - * gnulib/lib/obstack.c, gnulib/lib/obstack_.h, - gnulib/lib/stdbool_.h: All moved to gnulib/m4 directory. - * m4/strtol.c, m4/xmalloc.c, m4/xstrdup.c, m4/xstrzdup.c: Ditto. - * m4/Makefile.am: Adjust. - * gnulib/Makefile.am (EXTRA_DIST): Name just the additional gnulib - macros we redistribute. - * gnulib/m4/Makefile.am: New file. Build libgnu.la convenience - library among others. - (GNULIB_SRCS, GNULIB_MACROS): Removed. - * Makefile.am (ACLOCAL_AMFLAGS): Adjust. - * config/m4-obstack.m4: Adjust. - * po/POTFILES.in: Adjust. - * configure.ac: Reformatting. Call newly imported gnulib macros. - * m4/builtin.c, m4/macro.c, m4/module.c, m4/utility.c: Removed - bogus calls of `#include "m4.h"'. - * Makefile.am: INCLUDES has been deprecated in favour of - AM_CPPFLAGS. - * m4/Makefile.am: Ditto. - * modules/Makefile.am: Ditto. - * src/Makefile.am: Ditto. - -2003-09-05 Gary V. Vaughan - - * config/Makefile.am: Reverting yesterdays patch for VPATH builds. - -2003-09-04 Gary V. Vaughan - - Migrate the obstack support into the gnulib directories for easy - synchronisation with upstream files in gnulib: - - * config/gnu-obstack.m4: Moved from here... - * config/m4-obstack.m4: ...to here. - * config/Makefile.am (SPECIFIC_MACROS): Adjust. - * m4/obstack.c, m4/obstack_.h: Moved from here... - * gnulib/obstack.c, gnulib/obstack.h: ...to here. - * po/POTFILES.in: Adjust. - * gnulib/Makefile.am (GNULIB_SRCS, GNULIB_MACROS): Adjust. - * m4/Makefile.am: Add a whole new section to link the obstack - sources from the gnulib tree if necessary. - * gnulib/m4/onceonly_2_57.m4, gnulib/m4/obstack.m4: New macros - from gnulib. - * config/m4-obstack.m4: Rewrite as a wrapper for - gnulib/m4/obstack.m4. - -2003-09-04 Gary V. Vaughan - - GNU M4 currently builds with a number of files adapted from - upstream sources. Recently the gnulib project on savannah.gnu.org - has pulled together a great many of these externally maintained - files. This delta is the beginnings of isolating those files - maintained in gnulib to make it easy to synchronise M4 with the - upstream files prior to releases. - - * Makefile.am (ACLOCAL_AMFLAGS): Mention gnulib/m4 macro - directory. - (SUBDIRS): Added new gnulib subdirectory. - * configure.ac (AC_CONFIG_FILES): Add new gnulib tree Makefiles. - * config/stdbool.m4: Moved from here... - * gnulib/m4/stdbool.m4: ...to here. - * m4/stdbool_.h: Moved from here... - * gnulib/lib/stdbool_.h: ...to here. - * gnulib/Makefile.am: New file. Make sure the gnulib tree is - distributed. - * m4/Makefile.am: Adjust gnulib/modules/stdbool:Makefile.am based - code to work with new stdbool_.h location. - (gnulib_srcdir): New. - -2003-09-04 Gary V. Vaughan - - * config/Makefile.am (MAINTAINERCLEANFILES, ACLOCAL_MACROS) - (STANDARD_TOOLS, SPECIFIC_MACROS): Needed `$(srcdir)/' for VPATH - builds to work. - (SPECIFIC_TOOLS): New variable. Moved mkstamp to here. - (EXTRA_DIST): Use it. - - * bootstrap: CVS autoreconf leaves file droppings. Remove - aclocal.m4t incase autoreconf doesn't. - -2003-08-29 Gary V. Vaughan - - * m4/gnu-obstack.h: Updated from CVS gnulib. For consistency with - the other gnulib imports, renamed to m4/obstack_.h. - * m4/obstack.c: Updated from CVS gnulib. - * m4/Makefile.am (EXTRA_HEADERS): Adjust. - * config/gnu-obstack.m4 (M4_AC_FUNC_OBSTACK): Merge in additional - header tests from gnulib obstack module. AC_CONFIG_LINKS knows - about vpath already, and $top_srcdir upsets CVS Automake, so the - $top_srcdir reference was removed. - - * m4/system-h.in: For consistency with the gnulib imports, renamed - to m4/system_.h. - * m4/Makefile (EXTRA_HEADERS): Adjust. - * configure.ac (AC_CONFIG_FILES): Adjust. - - * m4/stdbool_.h: New file from gnulib for systems without their - own. - * m4/Makefile.am: Add snippets from gnulib for C99 bool support. - * config/stdbool.m4: New file. Macros from gnulib for same. - * configure.ac: Use it. - -2003-08-27 Gary V. Vaughan - - * config/debug.m4: `perl -pi.bak -e 's/(Copyright) (\d)/$1 (C) $2/g'` - * config/gmp.m4: Ditto. - * config/gnu-obstack.m4: Ditto. - * config/stackovf.m4: Ditto. - * m4/builtin.c: Ditto. - * m4/debug.c: Ditto. - * m4/error.c: Ditto. - * m4/error.h: Ditto. - * m4/gnu-obstack.h: Ditto. - * m4/hash.c: Ditto. - * m4/hash.h: Ditto. - * m4/input.c: Ditto. - * m4/m4.c: Ditto. - * m4/m4module.h: Ditto. - * m4/m4private.h: Ditto. - * m4/macro.c: Ditto. - * m4/module.c: Ditto. - * m4/obstack.c: Ditto. - * m4/output.c: Ditto. - * m4/path.c: Ditto. - * m4/regex.c: Ditto. - * m4/regex.h: Ditto. - * m4/strtol.c: Ditto. - * m4/symtab.c: Ditto. - * m4/syntax.c: Ditto. - * m4/utility.c: Ditto. - * m4/xmalloc.c: Ditto. - * m4/xstrdup.c: Ditto. - * m4/xstrzdup.c: Ditto. - * modules/evalparse.c: Ditto. - * modules/format.c: Ditto. - * modules/gnu.c: Ditto. - * modules/import.c: Ditto. - * modules/load.c: Ditto. - * modules/m4.c: Ditto. - * modules/m4.h: Ditto. - * modules/modtest.c: Ditto. - * modules/mpeval.c: Ditto. - * modules/perl.c: Ditto. - * modules/shadow.c: Ditto. - * modules/stdlib.c: Ditto. - * modules/time.c: Ditto. - * modules/traditional.c: Ditto. - * src/freeze.c: Ditto. - * src/getopt.c: Ditto. - * src/getopt1.c: Ditto. - * src/m4.h: Ditto. - * src/main.c: Ditto. - * src/stackovf.c: Ditto. - - * config/gmp.m4 (M4_AC_LIB_GMP): Use AC_INCLUDES_DEFAULT: - ac_default_headers is an autoconf internal variable. - * config/gnu-obstack.m4 (M4_AC_FUNC_OBSTACK): Ditto. - * config/stackovf.m4 (M4_AC_SYS_STACKOVF): Ditto. - - * configure.ac (AC_CONFIG_FILES): Add tests/atlocal. - * tests/Makefile.am (TESTS_ENVIRONMENT): Revert the 2003-08-14 - delta. - -2003-08-15 Gary V. Vaughan - - * configure.ac (AC_HEADER_STDBOOL, INCLUDE_STDBOOL_H): Check for - C99 bool. - * system-h.in (m4_boolean): Removed in favour of using C99 bool if - possible or faking one with a typedef. Changed all callers. - -2003-08-15 Gary V. Vaughan - - Still cleaning up the users' module API, by taking out the stuff - that isn't used by any existing modules, and moving specialised - functions out of libm4 and into the module they are used by. - - * m4/m4module.h (m4_skip_space): No need to export this. Moved... - * m4/utility.c (m4_skip_space): ...to here the home of its only - use, made static and renamed to `skip_space'. Changed all - callers. - * m4/m4module.h (m4_expand_ranges): Removed prototype. - * m4/utility.c (m4_expand_ranges): Moved definition from here... - * modules/m4.c (m4_expand_ranges): ...to here, and exported using - ltdl. - * modules/m4.h (m4_expand_ranges_func): For lt_dlsym import - casting . - * modules/gnu.c (builtin_syntax): Import and use in this - builtin implementation. - * m4/m4module.h (M4_DEBUG_PRINT1, M4_DEBUG_PRINT2, M4_DEBUG_PRINT3): - Not used. Deleted. - * m4/macro.c (trace_flush): Except here where the macro is now - manually inlined. - * m4/m4module.h (M4_DEBUG_MESSAGE, M4_DEBUG_MESSAGE1) - (M4_DEBUG_MESSAGE2, M4_DEBUG_MESSAGE3): Only used internally, so - moved... - * m4/m4private.h (M4_DEBUG_MESSAGE, M4_DEBUG_MESSAGE1) - (M4_DEBUG_MESSAGE2, M4_DEBUG_MESSAGE3): ...to here. - -2003-08-14 Gary V. Vaughan - - * config/gnu-obstack.m4 (M4_AC_FUNC_OBSTACK): Use the interrim new - compiler based AC_CHECK_HEADER that was introduced in - autoconf-2.56. - * config/stackovf.m4 (M4_AC_SYS_STACKOVF): Ditto. - * config/gmp.m4 (AC_LIB_GMP): Ditto. And renamed to M4_AC_LIB_GMP. - * configure.ac: Use renamed M4_AC_LIB_GMP. - - * config/debug.m4 (M4_AC_CHECK_DEBUGGING): Don't AC_REQUIRE a - macro that requires arguments! This stops the shell's bad - substitution error at configure time. - - * tests/Makefile.am (TESTS_ENVIRONMENT): Now we can pass make - variables to the testsuite shell. Set the value of USE_GMP so - that the gmp test will run! - (check-local, clean-local): Use the TESTS_ENVIRONMENT variable. - -2003-08-11 Gary V. Vaughan - - Libltdl already has an excellent mechanism for accessing C symbols - in modules. Lets use that! Remove all the exporting cruft and - just use lt_dlsym in conjunction with a few conventions to - simplify module writers' jobs. Also removed the table address - caching code and otherwise simplified the module loader quite a - bit. To access exported symbols in other modules, first the - exporting module must name the symbols _LTX_, - and the importing module must define a function type called - _func. The importer then adds - M4_MODULE_IMPORT(, ) at the top of any function - that wishes to call out to the exported functions. Care must be - taken that is non-NULL in the importing module incase - M4_MODULE_IMPORT fails, but otherwise it can be called as if the - definition was in the importers source. Study - `modules/{gnu.c,m4.{c,h}' for a model example. At the moment, - m4_module_import will attempt to automatically load a module - required for symbol access if it is not loaded already. - - * TODO: Removed the items fixed in this delta. - * m4/ltdl.c (lt_dlhandle_find): New function to find a handle by - module name. - * m4/ltdl.h (lt_dlhandle_find): Declare it. - * m4/module.c (m4_module_unload): Use it. - * src/freeze.c (reload_frozen_state): Ditto. - * m4/m4module.h (m4_export): Deleted. Removed all references. - (M4_MODULE_IMPORT): New user convenience macro for importing - arbitrary symbols from other modules. - * m4/module.c (m4_module_import): New function to service - M4_MODULE_IMPORT macro. - (module_data): Removed. Looking up the tables on demand with - lt_dlsym, rather than caching their addresses here simplifies the - code substantially. - (m4_get_module_builtin_table, m4_get_module_macro_table): - Removed. Changed all callers. - (set_module_macro_table, set_module_builtin_table): Renamed to - install_macro_table and install_builtin_table respectively, and - simplified now that the cache is no more. - * modules/gnu.c (builtin_symbols): Use this new mechanism to - import m4_dump_symbols from the m4 module. - (builtin_esyscmd): Likewise for m4_set_sysval and - m4_sysval_flush. - * modules/m4.c (m4_export_table): Removed. Functions are - addressed with the new mechanism which doesn't need this. - (m4_set_sysval): New exported accessor function to prevent - problems with variable access on inferior architectures. - * modules/m4.h (m4_sysval_flush_func, m4_set_sysval_func) - (m4_dump_symbols_func): Typedefs required by M4_MODULE_IMPORT so - that we can have some type safety. - * modules/modtest.c (export_test): C level exported function for - testing the new import mechanism. - * modules/import.c: New file for the import end of the test. - * modules/Makefile.am (pkglibexec_LTLIBRARIES): Added import.la. - * tests/modules.at: New test cases for intermodule symbol - importing. - -2003-08-07 Gary V. Vaughan - - * m4/m4module.c (m4_string): Moved from here... - * m4/m4private.c (m4_string): ...to here. - - * m4/utility.c (dumpdef_cmp): Removed stale declaration. - -2003-07-29 Gary V. Vaughan - - * m4/m4module.h (M4_DEFAULT_NESTING_LIMIT): This value is - already available to module writers through - m4_{get,set}_nesting_limit_opt(), so moved from here... - * m4/m4.c (DEFAULT_NESTING_LIMIT): ...to here and renamed. - (m4_create): Use it. - -2003-07-28 Gary V. Vaughan - - Aside from auditing path.c for m4module.h api obfuscation, this - delta introduces the concept of private struct members in opaque - data types to GNU m4: See the STYLE file for details. - - * TODO: Remind ourselves that a rewrite of path.c is needed. - * m4/m4module.h (m4_search_path, struct m4_search_path_info): - Moved from here... - * m4/m4private.h (m4__search_path, m4__search_path_info): ...to - here and renamed. These type definitions are for internal api use - only. Changed all callers. - * m4/m4module.h (m4_search_path_env_init, m4_search_path_add): - Moved from here... - * m4/path.c (search_path_env_init, search_path_add): ...to here - and renamed. These calls were never used outside this file. - Changed all callers. - (dirpath): Moved functionality of this static declaration... - * m4/m4private.h (struct m4): ...to this new internal only - search_path field. Changed all callers. - (m4__get_search_path): Added new internal api accessor. - * m4/path.c (m4_search_path_info_new): Removed. Not used. - (m4_include_init): Removed... - * m4/m4.c (m4_create): ...because the new m4 field is now - initialised here. - (m4_delete): Recycle search_path memory. - * src/main.c (main): Don't call m4_include_init now that it's - gone! - * doc/STYLE: Document convention for private fields in opaque - ADTs. - -2003-07-24 Gary V. Vaughan - - Sometimes exporting the address of a symbol from a module isn't - enough for other modules to call that symbol correctly. If - custom data types are used for function parameters, they need to - be known to the caller. This change introduces the concept of - $(prefix)/include/modules/$(modulename).h to declare those - structures. Also we move m4_dump_symbols from libm4 to the m4 - module to show this concept in action. - - * m4/m4module.h (m4_dump_symbol_data): Moved from here... - * modules/m4.h (m4_dump_symbol_data): ...to this new file for - exporting data structures from modules/m4.c. - * modules/m4.c, modules/gnu.c: Include it. - * modules/Makefile.am (pkgmodinc_HEADERS): Install it. - * m4/m4module.h (m4_dump_symbol_CB, m4_dump_symbols): Removed - prototypes. - * m4/utility.c (dumpdef_cmp, m4_dump_symbol_CB, m4_dump_symbols): - Moved from here... - * modules/m4.c (dumpdef_cmp_CB, dump_symbol_CB, m4_dump_symbols): - ...to here, with slight renaming. - (m4_export_table): Prototype and add m4_dump_symbols. - * m4/symtab.c (m4_is_symbol_value_void): Needed for an external - definition of m4_dump_symbols. - * m4/m4module.h (m4_is_symbol_value_void): Prototype it. - * m4/m4private.h (m4_is_symbol_value_void): Fast macro version. - -2003-07-24 Gary V. Vaughan - - Create an export table in modules/m4.c in readiness for beefing up - the module loader to track module exports and imports. - - * m4/m4module.h (m4_debug_flush_files): Removed prototype. - * m4/debug.c (m4_debug_flush_files): Moved... - * modules/m4.c (m4_sysval_flush): ...to here and renamed. - * modules/gnu.c (builtin_esysval): Use it. - * m4/m4module.h (m4_export): New type for declaring module symbols - for export. - * modules/m4.c (m4_export_table): List symbols exported from this - module for use by other modules. - -2003-07-24 Gary V. Vaughan - - An experiment: There is loads of code in libm4 which should be in - the m4 module, but is also used by another module. Just because - some linkers won't cope with calls across dynamic runtime loaded - objects I initially left the code in libm4. It will tidy the - module api immensely if this code moves to the right place, I just - need to remember to invent a suitable calling mechanism at some - point. For now, only modules that are statically linked and - preloaded will get this treatment, so the only platforms that will - break are those that require all symbols to be resolved at link - time. - - * TODO: Reminder that what I am doing could reduce portability - unless I do something more robust later. - * m4/m4module.h (m4_sysval): No longer exported from libm4. - * m4/utility.c (m4_sysval): No longer declared in libm4. - * modules/Makefile.am: Reformatting. - * modules/m4.c (m4_sysval): Declare it at place of use. - * modules/gnu.c (m4_sysval): Import it for use in esyscmd. - -2003-07-23 Gary V. Vaughan - - * m4/m4module.h: Reformatting and rearranging lines a bit. - (m4_obstack): Save typing by typedefing `struct obstack'. Changed - all users. - (m4_call_macro, m4_expand_input): Renamed... - (m4_macro_call, m4_macro_expand_input): ...to these. Changed all - callers. - (m4_expansion_level, m4_process_macro): Moved... - * m4/macro.c (expansion_level, process_macro): ...to here, and - made static. - - * m4/m4module.h (program_name): Not used by modules at all, so - moved... - * src/main.c (program_name): ...to here. - (print_program_name): Renamed... - (print_program_name_CB): ...to conform to the STYLE guide. - -2003-07-23 Gary V. Vaughan - - More refactoring of the m4module.h API. Replace #defines with an - enum, and move non-public functions out of the public API. - - * m4/debug.c (stdarg.h, varargs.h): Remove variadic header - inclusion. - * m4/macro.c (stdarg.h): Add ANSI C variadic header. - * m4/debug.c (m4_debug, trace): Moved... - * m4/m4private.h (struct m4): ...to fields of this struct. - (m4_get_debug_file, m4_get_trace_messages): New fast access macros - for the new fields. - * m4/debug.c (m4_debug_init, m4_debug_exit): Removed functions... - * src/main.c (m4_debug_init, m4_debug_exit): ...invocations... - * m4/m4.c (m4_create, m4_delete): ...and handled here instead. - * m4/m4module.h (m4_context_field_table): Add entries for new - debug_file and trace_messages fields. - (M4_DEBUG_TRACE_ARGS, M4_DEBUG_TRACE_EXPANSION) - (M4_DEBUG_TRACE_QUOTE, M4_DEBUG_TRACE_ALL, M4_DEBUG_TRACE_LINE) - (M4_DEBUG_TRACE_FILE, M4_DEBUG_TRACE_PATH, M4_DEBUG_TRACE_CALL) - (M4_DEBUG_TRACE_INPUT, M4_DEBUG_TRACE_CALLID) - (M4_DEBUG_TRACE_VERBOSE): Replaced #defines with an enum. - (m4_is_debug_bit): New macro to simplfy checks against the debug - bits above. - (m4_trace_format, m4_trace_header, m4_trace_flush) - (m4_trace_prepre, m4_trace_pre, m4_trace_post): Removed - prototypes. - * m4/debug.c (m4_trace_format, m4_trace_header, m4_trace_flush) - (m4_trace_prepre, m4_trace_pre, m4_trace_post): Moved... - * m4/macro.c (trace_format, trace_header, trace_flush) - (trace_prepre, trace_pre, trace_post): ...to these newly static - functions, since they are only ever used from this file. Changed - all callers. - -2003-07-17 Gary V. Vaughan - - Change the macros for checking syntax so that matching against - multiple possible syntax classes can be done with a single - comparison some of the time. The various classes are now bits of - an int that can be checked with bitwise logic operators. - - * m4/m4module.h (M4_SYNTAX_IGNORE, M4_SYNTAX_OTHER) - (M4_SYNTAX_SPACE, M4_SYNTAX_OPEN, M4_SYNTAX_CLOSE, M4_SYNTAX_COMMA) - (M4_SYNTAX_DOLLAR, M4_SYNTAX_ACTIVE, M4_SYNTAX_ESCAPE) - (M4_SYNTAX_ASSIGN, M4_SYNTAX_ALPHA, M4_SYNTAX_NUM) - (M4_SYNTAX_LQUOTE, M4_SYNTAX_RQUOTE, M4_SYNTAX_BCOMM) - (M4_SYNTAX_ECOMM): Replaced #defines with an enum. - (M4_SYNTAX_ALNUM): Removed. Changed all callers. - (M4_IS_IGNORE, M4_IS_OTHER, M4_IS_SPACE, M4_IS_OPEN, M4_IS_CLOSE) - (M4_IS_COMMA, M4_IS_DOLLAR, M4_IS_ACTIVE, M4_IS_ESCAPE) - (M4_IS_ASSIGN, M4_IS_ALPHA, M4_IS_NUM, M4_IS_LQUOTE, M4_IS_RQUOTE) - (M4_IS_BCOMM, M4_IS_ECOMM, M4__IS_STRING, M4_IS_IDENT): Removed. - Replace all calls with invocations of these... - (m4_is_syntax, m4_has_syntax): ...New macros. - * src/freeze.c (produce_syntax_dump): Remove mask argument, which - is no longer required with new macros. Changed all callers. - -2003-07-15 Gary V. Vaughan - - * m4/input.c (CHAR_EOF, CHAR_BUILTIN, CHAR_RETRY): These token - values are returned as part of the internal interface, so they - need to be moved... - * m4/private.h: ...to here. - * m4/macro.c (expand_token): Check for out of range - m4_peek_input() results before looking up in the syntax table. - (collect_arguments): Ditto. - - * NEWS: Note `$' syntax class. - -2003-07-08 Paul Eggert and - Gary V. Vaughan - - Conform to POSIX if the POSIXLY_CORRECT environment is set. - --traditional `define' now smashes all the definitions. - - * NEWS: Explain this. - * doc/m4.texinfo (Defn): `defn' takes any number of arguments. - (Extensions): Explain that extensions that are incompatible with - POSIX are disabled if POSIXLY_CORRECT is set. - (Incompatibilities): Remove. - (Define, Other Incompat): Explain difference - between GNU and POSIX behavior of define, pushdef, popdef. - * m4/m4.c (m4_get_posixly_correct_opt): New undef. - * m4/m4module.h (m4_context_opt_bit_table): Add POSIXLY_CORRECT entry. - * m4/m4private.h (M4_OPT_POSIXLY_CORRECT_BIT): New macro. - (m4_get_posixly_correct_opt): New macro. - * m4/m4macro.c (m4_process_macro): Disable $10, $abc etc. if - POSIXLY_CORRECT. - * modules/m4.c (builtin_functions): defn now takes any number of args. - (builtin_define): Smash all the definitions if - POSIXLY_CORRECT. - (builtin_defn)): Allow any number of arguments. - (builtin_undivert): Do not allow nonnumeric arguments - if POSIXLY_CORRECT. - * src/main.c (main): Set posixly-correct behavior if either - POSIXLY_CORRECT is set, or if -G is given. - * tests/builtins.at: New test for smashed definitions. - -2003-06-27 Gary V. Vaughan - - * doc/m4.texinfo (Changesyntax): Document Dollar syntax class. - * m4/m4module.h (M4__SYNTAX_STRING): New syntax class. Be careful - not to slow the parser down. - (M4__IS_STRING): New macro to test string syntax class membership. - * m4/syntax.c: Adjust docucomment. - (m4_syntax_create): Add a default M4_SYNTAX_DOLLAR element. - (m4_syntax_code): Translate `$' -> M4_SYNTAX_DOLLAR. - * m4/input.c (init_builtin_token): Comment typo. - (m4__next_token): Comment typo. - Accept M4_SYNTAX_DOLLAR items into M4_TOKEN_STRING type tokens - by using the new M4__IS_STRING macro. - * m4/macro.c (m4_process_macro): Use M4_IS_DOLLAR to test for - variable references in macro expansions. - - * doc/m4.texinfo (Eregexp and Regexp): Typo. - (Epatsubst and Patsubst): Typo. - (Eval): Typo. - -2003-06-26 Gary V. Vaughan - - Move the global variables that pertain to syntax to a new `struct - m4_syntax_table', and then add one of these to `struct m4'. The - ripple effect through the code to both change formerly global - references, and make sure a suitable context is available in - lexical scope is disproportionately large compared to the size of - the change proper. This change is a large part of decoupling - syntax.c from the rest of the code that uses it. - - * m4/m4private.h (struct m4): Add a syntax field. - * m4/m4.c (m4_create): Initialise it, - (m4_delete): Recycle it. - (m4_get_symtab): Remove hand coded version... - (m4_get_symbol_table): ...and generate this with cpp. Changed all - callers. - * m4/m4module.h (m4_context_field_table): Add an extra field so we - can generate m4_get_symbol_table. Add a new row for - m4_get_syntax_table. - (M4SYNTAX): Syntactic sugar for module writers. - (m4_symtab): Renamed to m4_symbol_table. Changed all callers. - (m4_syntax_table): New home for syntax related formerly global - variables. - * m4/m4private.h (struct m4_syntax_table): Define it. - * m4/input.c (m4_input_init): Initialisation of these formerly - global variables moved... - * m4/syntax.c (m4_syntax_create): ...to here. - * m4/input.c (m4_input_exit): And similarly, recycling of the - memory used by those values moved... - * m4/syntax.c (m4_syntax_delete): ...to here. - * m4/m4module.h (DEF_LQUOTE, DEF_RQUOTE, DEF_BCOMM, DEF_ECOMM): - Moved to m4/m4private.h. - * m4/syntax.c (m4_get_syntax_lquote, m4_get_syntax_rquote) - (m4_get_syntax_bcomm, m4_get_syntax_ecomm) - (m4_is_syntax_single_quotes, m4_is_syntax_single_comments) - (m4_is_syntax_macro_escaped): New accessors for m4_syntax_table - objects. Changed all callers that used to directly access the - global equivalents. - (m4__single_quotes, m4__single_comments, m4__use_macro_escape): - Removed and incorporated into m4_syntax_table structure. - * m4/utility.c (lquote, rquote, bcomm, ecomm): Ditto. - * m4/syntax.c (m4_set_syntax): Now returns an error status, - instead of requiring a `struct m4' to generate its own errors. - Changed all callers. - * src/main.c (main): Now that the syntax table is initialised as - part of m4_create, we have to manually wipe the syntax entries if - we are about to read a frozen file. - -2003-06-26 Gary V. Vaughan - - * doc/STYLE: Added notes on callback naming schemes. - - * m4/module.c (m4_set_module_macro_table) - (m4_set_module_builtin_table): Declarations weren't changed when - definitions were renamed on 2003-06-19. - - * m4/hash.c (m4_hash_resize): ifdefed out. This function is - neither used nor particularly appropriate since it exposes the - internal workings of the hash module. I haven't yet decided - whether to remove it entirely. - -2003-06-20 Gary V. Vaughan - - Two related changes, and a huge knockon effect throughout the - source: Moved the option variables out of global space and into - `struct m4'; made `m4_symtab' a real datatype, so that its api - is not marred passing `struct m4' around just so it can decide - whether to keep traced symbol names or not. Added setters and - getters for the formerly global option variables, and obviously - changed a vast number of functions to take a `struct m4' and use - the getter funcs to find option values. - - * m4/utility.c (interactive, sync_output, debug_level) - (no_gnu_extensions, prefix_all_builtins, suppress_warnings) - (max_debug_argument_length, warning_status, nesting_limit) - (discard_comments): Removed. - * m4/m4module (warning_status, no_gnu_extensions, nesting_limit) - (debug_level, max_debug_argument_length, prefix_all_builtins) - (suppress_warnings, discard_comments, interactive, sync_output): - Removed from here... - * m4/m4private.h (struct m4): ...and equivalent fields added to - this structure. - (m4_get_warning_status_opt, m4_get_no_gnu_extensions_opt) - (m4_get_nesting_limit_opt, m4_get_debug_level_opt) - (m4_get_max_debug_arg_length_opt, m4_get_prefix_builtins_opt) - (m4_get_suppress_warnings_opt, m4_get_discard_comments_opt) - (m4_get_interactive_opt, m4_get_sync_output_opt): Fast access - macros for the new fields. - * m4/m4module.h (m4_context_field_table) - (m4_context_opt_bit_table): Helper macros used to generate - prototypes, setters and getters for new option fields - consistently. - * m4/m4.c (m4_get_warning_status_opt, m4_get_no_gnu_extensions_opt) - (m4_get_nesting_limit_opt, m4_get_debug_level_opt) - (m4_get_max_debug_arg_length_opt, m4_get_prefix_builtins_opt) - (m4_get_suppress_warnings_opt, m4_get_discard_comments_opt) - (m4_get_interactive_opt, m4_get_sync_output_opt) - (m4_set_warning_status_opt, m4_set_no_gnu_extensions_opt) - (m4_set_nesting_limit_opt, m4_set_debug_level_opt) - (m4_set_max_debug_arg_length_opt, m4_set_prefix_builtins_opt) - (m4_set_suppress_warnings_opt, m4_set_discard_comments_opt) - (m4_set_interactive_opt, m4_set_sync_output_opt): Addressable - setter and getter functions generated by cpp from - m4_context_field_table and m4_context_opt_bit_table, exported as - part of the module api. Changed all callers. - * m4/symtab (struct m4_symtab): Used as the concrete type for - m4_symtab now. - (m4_symtab_create): Allocate and initialise a new struct. - (m4_symtab_apply): New function that works like m4_hash_apply, but - with different callbacks specific to symbol tables. Changed all - callers. - (symbol_destroy, arg_destroy, arg_copy): Renamed - symbol_destroy_CB, arg_destroy_CB, arg_copy_CB to remind me that - they have unused parameters for a reason! - (dump_symbol_CB): New callback to dump the contents of a single - symbol. - (symtob_dump): Rewritten in terms of dump_symbol_CB. - * m4/utility.c (m4_dump_symbol): Renamed to m4_dump_symbol_CB. - Changed all callers. - * m4/m4.c (m4_create): By default point the `nuke_trace_bit' field - of the contained `m4_symtab' at the `no_gnu_extensions' field. - Although I'm not convinced these semantics are correct, they are - at least consistent with how things were before this delta. Also - set the default nesting limit to M4_DEFAULT_NESTING_LIMIT. - -2003-06-19 Gary V. Vaughan - - Tie down the interface to libm4 some more. Make more structures - opaque to modules by moving them to m4private.h, and writing - setters and getters. To win back the speed penalty for doing this - also wrote macroized versions that do know about structure layout - in m4private.h and #include that file into modules when NDEBUG is - defined at compile time. There are still some accessor macros in - m4private.h that need to go, but that is not necessary to clean - the module api up. - - * m4/m4module.h (m4_symbol_type): Moved... - * m4/m4private.h (m4__symbol_type): ...to here. - * m4/symtab.c (m4_get_symbol_value, m4_get_symbol_traced) - (m4_set_symbol_traced, m4_set_symbol_name_traced) - (m4_is_symbol_text, m4_is_symbol_func, m4_get_symbol_text) - (m4_get_symbol_func, m4_symbol_value_create) - (m4_symbol_value_delete, m4_set_symbol_value_text) - (m4_set_symbol_value_func): New exported api to symbols. - (m4_get_symbol_value_type): Replaced by m4_is_symbol_value_text - and m4_is_symbol_value_func. - * m4/m4module.h: Prototype these guys. - * m4/module.c (m4_set_module_macro_table) - (m4_set_module_builtin_table): Make these static, there is no - reason to pollute the api with them. - * m4/m4private.h: Reformatting. - (m4_get_symtab): Only define when NDEBUG is defined. - (m4_get_symbol_value, m4_get_symbol_traced) - (m4_set_symbol_traced, m4_set_symbol_name_traced) - (m4_is_symbol_text, m4_is_symbol_func, m4_get_symbol_text) - (m4_get_symbol_func, m4_symbol_value_create) - (m4_symbol_value_delete, m4_set_symbol_value_text) - (m4_set_symbol_value_func): Macro implementations of the new - functions when NDEBUG is defined. - (SYMBOL_TRACED, SYMBOL_VALUE, SYMBOL_TYPE, SYMBOL_TEXT) - (SYMBOL_FUNC, VALUE_TYPE, VALUE_TEXT, VALUE_FUNC): Removed. - Superceded by the above. All callers changed. - (M4ARG): Removed. This is no longer different to the - m4/m4module.h definition. - * modules/gnu.c, modules/m4.c: Only include m4private.h when - NDEBUG is defined. That way we exercise the same (albeit slower) - api that external modules must use. - -2003-06-18 Gary V. Vaughan - - Renamed some of the types and their accessors to make more sense. - Now we have a SYMTAB in which we store SYMBOLs, and each SYMBOL - has a stack of SYMBOL_VALUEs. - - * m4/m4module.h (m4_token, m4_get_token_type, m4_get_token_text) - (m4_get_token_func, m4_token_copy): Renamed to m4_symbol_value, - m4_get_symbol_value_type, m4_get_symbol_value_text, - m4_get_symbol_value_func and m4_symbol_value_copy respectively. - Changed all callers. - (m4_symbol_type): s/M4_TOKEN_/M4_SYMBOL_/ - (m4_get_token_type): Renamed - * m4/input.c (m4_next_token): Renamed to m4__next_token, and moved - to the internal api. - * m4/m4private.h: s/TOKEN_ARG_/SYMBOL_ARG_/ - s/TOKEN_/VALUE_/ - (m4__symtab_init, m4__symtab_exit): Removed prototypes. - (m4_token_arg): Renamed to m4_symbol_arg. Changed all callers. - (m4__token_type): Moved here from m4module.h. - (m4__next_token): Renamed from m4_next_token. - * m4/symtab.c: Removed some of the parameterised macro support - functions for modularisation later. - (m4_token_copy): Renamed to m4_symbol_value_copy, and use new - m4_hash_dup to perform a true deep copy of the SRC. - (arg_copy): Callback for m4_symbol_value_copy. - * utility.c (m4_token_get_type, m4_token_text, m4_token_func): - Renamed to m4_get_symbol_value_type, m4_get_symbol_value_text and - m4_get_symbol_value_func. Changed all callers. - -2003-06-18 Gary V. Vaughan - - Tidy up style of hash.[ch] in accordance with doc/STYLE. - - * m4/hash.c: Internal symbol renaming and formatting. - (m4_hash_dup): New function to facilitate deep copies of hash - tables. - (m4_hash_apply_func): Returns a void* now, which is a richer type - for returning exceptions (NULL means keep going). - (m4_hash_apply): Ditto. - * m4/hash.h: Declare exported symbols with an explicit extern. - Reformated. - -2003-06-17 Gary V. Vaughan - - Still refactoring furiously. This delta represents a change in - semantics to symtab.c. Instead of building temporary m4_tokens - in the caller, and copying fields in the methods, we now create - the actual m4_token for hashing in the caller so the methods just - slot them in directly. Also, this means that we don't lookup a - symbol and get back an allocated but VOID token to copy fields - into, we create the token we want to push and pass that to - m4_symbol_define or m4_symbol_pushdef. And that's it. There are - a few other small changes to stop knowledge of the implementation - of symtab.c leaking out into other files. - - * m4/macro.c (expand_argument): Comment typo corrected. - * m4/symtab.c (symtab_fetch): New function to fetch the address of - an interned symbol. - (m4_symbol_pushdef): Take an extra value parameter and use this - directly as the new top of the value stack. All callers changed - to build a token and pass responsibility for memory in, rather - than copying as we used to. - (m4_symbol_define): Also use the new value parameter directly as a - replacement for the top of the value stack. All callers changed - to build a token as above. - (m4_set_symbol_traced): New function to set the traced bit on the - named symbol, creating it if necessary. - (symbol_popval): The guts of the old m4_symbol_popdef. - (m4_symbol_popdef): Use it. - * m4/builtin.c (m4_symbol_set_token): Removed, - (m4__symbol_set_builtin, m4__symbol_set_macro): Removed and - replaced... - * m4/module.c (m4_set_module_builtin_table) - (m4_set_module_macro_table): ...with these more orthogonal - functions. - * m4/m4module.h (m4_macro_pushdef, m4_macro_define) - (m4_builtin_pushdef, m4_builtin_define): Removed. No longer - required. - * m4/builtin.c (M4_ARG_SIGNATURE_DEFAULT_SIZE) - (m4_arg_signature_parse): Moved... - * m4/symtab.c: ...to here. - * m4/input.c (m4_token_copy): Arghh... I'm amazed this didn't - screw something up. Moved... - * m4/symtab.c (m4_token_copy): ...to here, and fixed so that it - actually does a proper deep copy of source to dest. - -2003-06-16 Gary V. Vaughan - - Further refactoring to stabilise the module API. Renaming some - functions for orthogonality, and judicious definition migration to - move things out of the set of exported symbols. - - * doc/STYLE: New file. Notes on coding style. - * m4/m4module.c: Updated bitrotted docucomment at the top of the - file. - (m4_module_name, m4_module_builtins, m4_module_macros): Renamed to - m4_get_module_name, m4_get_module_builtin_table, - m4_get_module_macro_table which are verb phrases. Changed all - callers. - * m4/builtin.c (m4_builtin_table_install, m4_macro_table_install): - Moved to... - * m4/module.c (m4_set_module_builtin_table) - (m4_set_module_macro_table): ...here, and renamed. Changed all - callers. - * m4/m4module.c (m4_module_data): This... - * m4/m4private.c (struct m4_module_data): ...and this... - * m4/module.c (module_data) ...consolidated here and no longer - exported. Changed all callers. - -2003-06-16 Gary V. Vaughan - - Begin work on lifting the curse of the global variables. To start - with create a `struct m4' context container, and replace - `m4__symtab' with `context->symtab' throughout. This means - initialising a context container in main, and adjusting many - functions between main and the module entry points so that the - container gets passed through. It would have been nice to - defer this until after 1.5, but it has a major effect on the - user's module writing ABI, so it needs to be addressed now - at - least in the areas that impact the ABI. An interrelated change - in the symtab API removes the dependency on a global symbol table, - and instead focuses on a passed table (from the context - container). - - * TODO: Reminders for finishing context functionality. - * m4/Makefile.am (libm4_la_SOURCES): Add m4.c. - * m4/m4.c: New file. Manage new struct m4 objects to eliminate - global variables and eventually allow m4 to be reentrant. - * m4/m4private.h (m4): Define the new structure here... - (M4_SYMTAB, m4_get_symtab): ...so we can have fast accessors that - don't carry the overhead of a function call. - * m4/m4module.h: Prototype extern functions from m4/m4.c. - (m4): Declare type for new struct m4 objects. - (M4SYMTAB): User macro to ease finding the symbol table for the - current context for module developers. - (m4_symbol_token): Renamed to m4_symbol_set_token which contains a - verb. - (M4_BUILTIN, m4_builtin_func, M4_BUILTIN_HANDLER) - (m4_builtin_define, m4_builtin_pushdef, m4_builtin_table_install) - (m4_call_macro, m4_dump_symbols, m4_expand_input) - (M4_FINISH_HANDLER, M4_INIT_HANDLE, m4_macro_define) - (m4_macro_pushdef, m4_macro_table_install, m4_module_load) - (m4_module_unload, m4_process_macro, m4_symbol_set_token): Add an - m4* context parameter. Changed definitions and all callers. - (m4_symtab): Alias for m4_hash to decouple the - m4_symtab api from m4_hash. - (m4_symtab_apply, m4_symtab_apply_func): Use m4_symtab instead of - m4_hash. - (m4_symtab_create): New function to return an initialised - m4_symtab. - (m4_symtab_delete): New function to delete an m4_symtab's memory. - (m4_symbol_define, m4_symbol_delete, m4_symbol_lookup) - (m4_symbol_popdef, m4_symbol_pushdef): Add an m4_symtab parameter - instead of simply using the global m4__symtab. Changed - definitions and all callers. - * m4/m4private.h (m4__symtab_remove_module_references): Ditto. - * m4/symtab.c (m4__symtab_init, m4__symtab_exit): Removed. - * src/main.c (main): Create a context and use that instead of the - former global m4__symtab. - -2003-06-13 Gary V. Vaughan - - * m4/hash.c (m4_hash_apply): Pass an initial hash table parameter - to the callback. Callbacks should not need to hardcode the - hashtable they are working from, nor should we have to waste the - userdata parameter to pass the table in. - * m4/hash.h (m4_hash_apply_func): Require the initial table - parameter. - * m4/symtab.c (symtab_destroy): Use the passed table instead - of hardcoding m4__symtab. - (m4_symbol_popdef): Don't use the userdata parameter to pass the - table to arg_destroy. - (arg_destroy): Use the hash parameter, ignore userdata. - * modules/m4.c (set_trace): Make it fit the m4_hash_apply_func - prototype. - (traceon, traceoff): Call set_trace with the extra initial - parameter. - -2003-06-13 Gary V. Vaughan - - More refactoring to stabilise the module api, this time for - symtab.c. Additionally, start to pay attention to function names - that don't contain a verb like they should. - - * m4/m4module.h (m4_symtab_apply): Reintroduced this function as a - wrapper for m4_hash_apply to decouple the symtab module from the - hash module. - (m4_symbol_builtin, m4_symbol_macro): Renamed to - m4__symbol_set_builtin and m4__symbol_set_macro. Changed all - callers. - (m4_symbol_delete): Create a macro version to save a function - call. - (m4_token_t, m4_data_t): These violate the POSIX reserved - namespace. Renamed to m4_token_type and m4_symbol_type. Changed - all callers. - (m4_token_type): Renamed to m4_token_get_type. - (m4_symtab, m4_symtab_init, m4_symtab_remove_module_references) - (m4_symtab_exit): Removed from the exported module - api... - * m4/m4private.h (m4__symtab, m4__symtab_init) - (m4__symtab_remove_module_references, m4__symtab_exit): ...and - renamed and added to the internal api. Changed all callers. - (m4_symtab_apply): A faster macro version of the function for - users of the internal api. - * m4/symtab.c (m4_symbol_destroy, m4_arg_destroy): Renamed to - symbol_destroy and arg_destroy. - (symtab_debug): Added a prototype. - (m4_symtab_apply, m4_symbol_delete): Moved to the end of the file - so that callers in this file get the faster macro versions from - m4/m4private.h. - -2003-06-12 Gary V. Vaughan - - Refactoring modules to rationalise the API into an external - documented (eventually!) API for use by modules in the `m4_' - namespace declared in m4/m4module.h, an internal API between the - source files we ship (including our shipped modules) in the `m4__' - namespace declared in m4/m4private.h and making the rest as - cohesive as possible with liberal use of the `static' keyword. - This change represents an audit to m4/module.c along these - guidelines. - - * m4/m4module.h (m4_module_close_all, m4_module_find_by_builtin): - Removed. No longer used. - (m4_module_close): Removed prototypes. - (m4_module_init, m4_module_open, m4_module_unload_all): Removed - from the exported module api... - * m4/m4private.h (m4__module_init, m4__module_open) - (m4__module_exit): ...and renamed and added to the internal api. - Changed all callers. - (BUILTIN_SYMBOL, MACRO_SYMBOL, INIT_SYMBOL, FINISH_SYMBOL): - Centralised definitions after renaming... - * m4/module.c (M4_BUILTIN_SYMBOL, M4_MACRO_SYMBOL, M4_INIT_SYMBOL) - (M4_FINISH_SYMBOL): ...and removing from here. - (m4_module_dlerror, m4_module_remove, m4_module_close) - (m4_caller_id): Not exported at all, so renamed to module_dlerror, - module_remove, module_close and caller_id. - (MODULE_SELF_NAME): New macro to make reporting self errors - easier. - (m4_module_load, module_close, module_remove): Use it. - * m4/m4private.h (USER_MODULE_PATH_ENV): Macro to hold "M4MODPATH" - name. - * src/main.c (main): Use it. - -2003-06-12 Gary V. Vaughan - - * README: Remove references to --enable-changeword, which has been - removed from the code. - -2003-06-11 Gary V. Vaughan - - Getting rid of the annoying bug with configure --enable-debug, - which spewed -e: command not found errors. This was an interaction - between libtool-1.5's LT_AC_COMPILER_OPTION, and config/debug.m4. - You'll need to re-bootstrap the m4 tree with cvs libtool (HEAD or - branch-1-5) to get the full fix. - - * config/debug.m4 (M4_AC_CHECK_DEBUGGING): Require libtools version - of AC_LIBTOOL_COMPILER_OPTION (which now requires LT_AC_PROG_SED), - and then use the probed value of $SED. - (AC_LIBTOOL_COMPILER_OPTION): Removed. Don't conditionally define - this, it messes up the AC_REQUIRE stack. - -2003-06-10 Gary V. Vaughan - - * m4/symtab.c (m4_symbol_popdef): Need to pass the hash address to - the destroy callback. - (m4_arg_destroy): Use the hash address to free the hash node key - field. - -2003-06-06 Gary V. Vaughan - - First cut at formal parameters in macros. - - * configure.ac (AC_REPLACE_FUNCS): Add xstrzdup. - * m4/xstrzdup.c: New file. - * m4/builtin.c (M4_ARG_SIGNATURE_DEFAULT_SIZE): Start size for - associative array of parameter names to details. - (m4_symbol_token): Capture macro names with parameter lists. - (m4_arg_signature_parse): And build an associative array to hang - from the symbol structure to map names to details. - * m4/hash.c (m4_hash_new): Break the m4_hash_new followed by - m4_hash_resize idiom. Now that we potentially add a little hash - table to many of the entries in the symbol table, added an extra - arg to set the initial size. Changed all callers. - (m4_hash_apply): New function that is basically a generalised - version of... - * m4/symtab.c (m4_symbol_apply): ...this. Now deleted. Adjusted - all callers to call m4_hash_apply instead. - (m4_arg_destroy): Recycle memory used by an m4_token_arg. - (m4_symbol_popdef): Use m4_arg_destroy to help recycle the - m4_arg_signature association that might be attached to the symbol, - * m4/hash.h (m4_hash_apply_func): Replacement type for... - * m4/m4module.h (m4_symtab_apply_func): ...this. Now deleted. - (M4_SYNTAX_ASSIGN): Placeholder for assigning default values in - parameter lists. - (M4_IS_ASSIGN): Detect characters with M4_SYNTAX_ASSIGN syntax. - (M4_IS_IDENT): Detect characters that can be safely used in - parameter names. - * m4/syntax.c (m4_syntax_init): Add an M4_SYNTAX_ASSIGN character. - * m4/macro.c: Corrected grammar in some comments. Use `token' - rather than `td' for m4_token variables. - (m4_process_macro): If we find a dollar followed by some - M4_IS_IDENT characters, replace that with the contents of the argv - entry with offset stored in the m4_token_arg associated with the - collected identifier. - -2003-06-05 Gary V. Vaughan - - Begin preparations for supporting formal parameters in m4 macros. - - * m4/m4private.h (struct m4_token_arg): Placeholder for holding - the details of a formal parameter. - (m4_token): Add an arg_signature member to hold a hash table for - looking up formal parameters. - * m4/input.c: Update more bitrotted comments. - (m4_push_builtin): Initialise arg_signature member. - (init_builtin_token): Copy arg_signature member. - * m4/m4module.h (m4_builtin_pushdef, m4_builtin_define) - (m4_macro_pushdef, m4_macro_define): Rewritten as macros to - replace... - * m4/builtin.c (m4_builtin_pushdef, m4_builtin_define) - (m4_macro_pushdef, m4_macro_define): ...these, And... - (m4_symbol_token): ...wrapped around this new function, which - vastly simplifies the arguments required by the functions it - replaces. - Changed all callers. - -2003-06-05 Gary V. Vaughan - - * m4/macro.c: Format changes. - -2003-06-04 Gary V. Vaughan - - * m4/input.c: Updated various bitrotted comments. - (m4_push_builtin): Just pass the whole m4_token, rather than - extracting all the fields in the caller. This also allows us to - check the token type for consistency. - (macro_funcs, macro_peek, macro_read, m4_push_macro, CHAR_MACRO): - Renamed to builtin_funcs, builtin_peek, builtin_read, - m4_push_builtin and CHAR_BUILTIN for consistency with the rest of - the code. Changed all callers. - (struct input_block): Similarly renamed u_m member to u_b, and - changed all callers. - (m4_next_token): Use bzero to initialise the data fields. - * m4/m4module (m4_push_macro): Renamed to m4_push_builtin. - -2003-05-29 Gary V. Vaughan - - These changes were necessary to get m4 to build on my iBook - running "powerpc-apple-darwin6.6" using Apples build of gcc "gcc - (GCC) 3.1 20020420 (prerelease)": - - * src/main.c: Don't include dlfcn.h, ltdl.h handles correct - inclusion of module loader headers. - * modules/Makefile.am: Use AM_LDFLAGS, not LDFLAGS. - * m4/Makefile.am: Ditto. - (libm4_la_LIBADD): Added $(LTLIBINTL). - * m4/utility.c (program_name): Removed declaration in favour of - the one already in error.c! - * m4/m4module.h (program_name): Define to program_invocation_name - when using GNU C library. Use an explicit extern declaration. - (interactive, sync_output, debug_level, hash_table_size) - (no_gnu_extensions, prefix_all_builtins, max_debug_argument_length) - (suppress_warnings, warning_status, nesting_limit, discard_comments) - (lquote, rquote, bcomm, ecomm, m4_bad_argc, m4_skip_space) - (m4_numeric_arg, m4_shipout_int, m4_shipout_string, m4_dump_args) - (m4_debug, m4_debug_init, m4_debug_exit, m4_debug_decode) - (m4_debug_flush_files, m4_debug_set_output, m4_debug_message_prefix) - (m4_trace_prepre, m4_trace_pre, m4_trace_post, m4_sysval) - (m4_expansion_level, m4_expand_ranges, m4_expand_input) - (m4_call_macro, m4_process_macro, m4_syntax_table, m4_current_file) - (m4_current_line, m4_current_diversion, m4_output_current_line): - Don't rely on default, use an explicit extern. - * m4/error.h (error, error_at_line, error_print_progname) - (error_message_count, error_one_per_line): Ditto. - * m4/ltdl.c: Update from CVS libtool. - * m4/ltdl.h: Ditto. - * commit: Update from CVS cvs-utils. - -2002-11-04 gettextize - - * po/Makefile.in.in: Upgrade to gettext-0.11.5. - * po/boldquot.sed: New file, from gettext-0.11.5. - * po/en@boldquot.header: New file, from gettext-0.11.5. - * po/en@quot.header: New file, from gettext-0.11.5. - * po/insert-header.sin: New file, from gettext-0.11.5. - * po/quot.sed: New file, from gettext-0.11.5. - * po/remove-potcdate.sin: New file, from gettext-0.11.5. - * po/Rules-quot: New file, from gettext-0.11.5. - -2002-11-04 Akim Demaille - - * doc/m4.texinfo (Esyscmd): Don't grep, use something easier: - running m4 itself. - * tests/others.at (iso8859): Use abs_srcdir, not srcdir. - -2002-11-04 Akim Demaille - - * config/Makefile.am (ACLOCAL_MACROS): Ship the Gettext macros. - -2002-11-04 Akim Demaille - - * configure.ac: Automake 1.7.1, Autoconf 2.54, Gettext 0.11.5, - used as `external', and Libtool 1.4.3. - (LINGUAS): Remove. - (LTLIBOBJS): Don't play with it. - * intl/: Remove. - * Makefile.am (SUBDIRS): Remove intl. - (ACLOCAL_AMFLAGS): Add -I config. - (EXTRA_DIST): Add config/config.rpath. - * po/LINGUAS: New. - * po/Makevars: New. - * modules/perl.c (M4INIT_HANDLER): Don't prototype xs_init. - -2002-05-29 Gary V. Vaughan - - Preparations for refactoring syntax tables to allow reverse - lookups [fetch me a M4_SYNTAX_OPEN], without compromising the - speed of normal lookups in an array of unsigned short. - - * m4/input.c (single_quotes, single_comments, use_macro_escape): - Moved from here... - * m4/m4private.h (m4__single_quotes, m4__single_comments, - m4__use_macro_escape): ...to here, and renamed. The `m4__' prefix - is for internal symbols which unavoidably pollute the global - namespace, but are not published APIs. - Adjusted all callers. - * m4/input.c (m4_syntax_init, m4_syntax_code, m4_set_quotes, - m4_set_comment, m4_set_syntax, set_syntax_internal, - unset_syntax_attribute): Moved from this file... - * m4/syntax.c: New. ...to this file. - Also added an m4_syntax_exit stub for orthogonality. - * src/main.c (main): Use it. - * m4/Makefile.am (libm4_la_SOURCES): Add syntax.c. - * m4/m4module.h: Reformatting. New prototypes. - -2002-05-29 Gary V. Vaughan - - * bootstrap (aclocal_apiversion): The aclocal apiversion is - distinct from the automake release number (in that the apiversion - apparently has no micro-version-component). - (aclocal_apilibdir): Use it. - -2002-05-28 Gary V. Vaughan - - * m4/hash.c (m4_hash_resize): New function. - * m4/hash.h: Add prototype. - * m4/symtab.c (m4_symtab_init): Use it. This could do with some - benchmarking to find a good value for, say, autoconf. This is - already a little quicker than before for me. - - * m4/symtab.c (m4_symtab_hash, m4_symtab_cmp): Moved from here... - * m4/hash.c (m4_hash_string_hash, m4_hash_string_cmp): .. to here, - and reenamed. - * m4/hash.h: Adjust prototypes. - -2002-01-22 Akim Demaille - - * bootstrap (aclocal_apilibdir): New, to cope with Automake's new - APIVERSION scheme. - * tests/Makefile.am (package.m4): New. - * tests/atlocal.in: Adjust to CVS Autotest. - * config/gnu-obstack.m4 (M4_AC_FUNC_OBSTACK): Use AC_LIBOBJ. - * configure.ac: LIBOBJ is a forbidden string. - Simplify AM_INIT_AUTOMAKE invocation. - * config/Makefile.am (ACLOCAL_MACROS): Add amversion.m4 and - options.m4. - -2002-01-21 gettextize - - * po/Makefile.in.in: Upgrade to gettext-0.10.40. - -2001-10-19 Akim Demaille - - * m4/module.c, m4/output.c, src/main.c: Normalize error messages. - -2001-10-19 Akim Demaille - - * m4/input.c (m4_next_token): Display where was opened what is - not closed. - -2001-10-19 Akim Demaille - - * m4/macro.c (expand_argument): Display where was opened what is - not closed. - -2001-10-18 Akim Demaille - - * m4/input.c, modules/m4.c: Formatting changes. - -2001-10-17 Gary V. Vaughan - - * bootstrap: s/configure.in/configure.ac/ - -2001-10-16 Gary V. Vaughan - - * m4/symtab.c (m4_symbol_destroy): This function calls - m4_symbol_popdef, which recycles a symbols memory when the last - definition is popped. Since we were passing the address of the - symbol name found in the symbol table, and it was being removed - partway through m4_symbol_destroy() we were referencing freed - memory for the balance of the function. Now we take a copy of the - symbol name tring and use that as a key into the symbol - table... that way if the original symbol name is freed, the copy - is still valid. - -2001-10-13 Akim Demaille - - * m4/ltdl.c: Update. - -2001-10-13 Akim Demaille - - * src/main.c, src/freeze.c, m4/debug.c, m4/input.c, m4/macro.c: - Don't gettextize internal error messages. - -2001-10-13 Akim Demaille - - * tests/macros.at (Arity and defn): New failing test. - (Arity, defn, and freeze): New. - - Fix `Arity and defn'. - - * m4/input.c (m4_push_macro): Don't forget the arity. - * modules/m4.c (defn): Likewise. - -2001-10-13 Akim Demaille - - * tests/builtins.at (pushdef/popdef, trace, trace2, trace3): Move - to... - * tests/macros.at (pushdef/popdef, Tracing Hanoi Towers) - (Propagation of traceon, Propagation of --trace): this new file. - -2001-10-13 Akim Demaille - - * m4/utility.c (m4_numeric_arg): Use the usual (argc, argv, ...) - interface instead of (name, argc...). - Upon failure, specify which argument was guilty. - Adjust callers. - -2001-10-13 Akim Demaille - - * modules/evalparse.c: Save translators' time: don't translate - internal error messages. - (m4_evaluate): Simplify/normalize error messages. - * doc/m4.texinfo (Eval): Adjust. - -2001-10-13 Akim Demaille - - * m4/macro.c (expand_macro): Let m4_bad_argc handle the cases - where no checking is needed. - * m4/utility.c (m4_bad_argc): Use the usual (argc, argv, ...) - interface instead of (name, argc...). - Adjust callers. - * modules/gnu.c (m4_patsubst_do): Don't check argc, done - elsewhere. - -2001-10-13 Akim Demaille - - * m4/utility.c (m4_bad_argc): Display user argument counts, i.e., - exclude the builtin name from the count. - * modules/m4.c (ifelse): Do not use the regular argc mechanism, as - calling ifelse with a single argument is valid. - * doc/m4.texinfo (Ifelse): Add an example where ifelse is invoked - with 1 and 2 args, mostly to strengthen the test suite. - -2001-10-13 Akim Demaille - - * m4/output.c (m4_make_diversion, m4_insert_file) - (m4_insert_diversion, +m4_freeze_diversions): Ansify. - -2001-10-12 Gary V. Vaughan - - * m4/input.c (init_builtin_token): Renamed from init_macro_token, - since we call these things builtins in the rest of the code! - - * modules/gnu.c (m4_regexp_compile): s/%0/%s/ - -2001-10-12 Gary V. Vaughan - - Rather than forcing each builtin definition to manage its own - argument range checking, tabulate the maxima and minima for all - builtins in each module. This forces us to consider what the - valid ranges for each builtin should be, and moves the checking - code out of each builtin implementation and into the builtin - caller infrastructure. - - * m4/m4module.h (struct m4_builtin): Add argument minima and - maxima. - * m4/m4private.h (struct m4_token): Reflect them here too. - * m4/input.c (struct input_block): ...and here. - (m4_token_copy): New function for token copying. - (init_macro_token): Copy them from a token to the input stack. - (m4_next_token): Don't forget to initialise them for text - macros. - * m4/macro.c (expand_argument): Use m4_token_copy, and also - check argument counts before calling the builtin handler. - * m4/symtab.c (m4_symbol_builtin): Take minima and maxima params. - (m4_symbol_macro): Likewise. - * m4/builtin.c (m4_builtin_pushdef): Add min_args and max_args - parameters. Updated all callers. - (m4_builtin_define): Ditto. - (m4_macro_pushdef, m4_macro_define): Ditto. - * m4/symtab.c (m4_symbol_builtin, m4_symbol_define): Ditto. - * modules/evalparse.c: Declare argument counts for defined - builtins and remove explicit calls to m4_bad_argc(). - * modules/gnu.c: Ditto. - * modules/load.c: Ditto. - * modules/m4.c: Ditto. - * modules/modtest.c: Ditto. - * modules/mpeval.c: Ditto. - * modules/perl.c: Ditto. - * modules/shadow.c: Ditto. - * modules/stdlib.c: Ditto. - * modules/time.c: Ditto. - * TODO: Updated. - -2001-10-10 Gary V. Vaughan - - The trace semantics now attach the trace bit to a symbol name. - For as long as a traceon(`foo') is active, calls to foo will be - traced regardless of intervening undefines or module unloads. - Fixed the flag propogation issues differently to the fixes - reverted with the last attempt at nailing down trace: - - * m4/m4private.h: This file is not visible outside of the m4 - source tree, so I removed all the `M4_' and `m4_' prefixes to save - on typing. Updated all clients. - (m4_token): New typedef contains the fields that need to be passed - around with the low level tokeniser. - (m4_token_data): Removed. - (m4_symbol): Now contains the traced flag again. - * m4/symtab.c: Rewritten again. Now we don't remove symbols with - the trace bit set. This change is contained entirely within this - module and doesn't leak out into the callers. Updated all - clients. - (m4_symbol_builtin, m4_symbol_macro): Adjusted to make use of the - new fields in m4_token. Updated all clients. - * m4/builtin.c (m4_builtin_pushdef): Needs a flags argument so - that `groks_macro_args' and `blind_if_no_args' flags are retained - when defn() results are passed around in m4 code. Updated all - callers. - (m4_builtin_define): Ditto. - (m4_macro_pushdef, m4_macro_define): Ditto. - * m4/input.c (struct input_block): Add a flags field to facilitate - the above. - (m4_push_macro): ...use it. - (init_macro_token): Retrieve it. - (m4_next_token): Initialise it. - * m4/macro.c (expand_argument): Copy it. - * m4/m4module.h: Adjust. - * tests/builtins.at: Adjust the expected output of the trace - tests to reflect the change in semantics. - * tests/modules.at (modules: trace): Check that unloading a - module which supplies a traced symbol definition doesn't lose te - trace bit. - -2001-10-07 Gary V. Vaughan - - * modules/gnu.c (m4_macro_table): Display the timetamp when - expanding __m4_version__. - - * configure.ac (--with-modules): Forgot a comma in the - AC_HELP_STRING parameter list. - -2001-10-05 Gary V. Vaughan - - * bootstrap: Remove aclocal.m4t when it is no longer required. - -2001-10-05 Akim Demaille - - * tests/Makefile.am: Adjust for gnuprog2. - * tests/m4.in: There can be a leading path. - * tests/modules.at (AT_CHECK_M4_MODTEST): No need for $4 and $5. - * tests/testsuite.at: Adjust to the most recent Autotest. - (AT_CHECK_M4_FILTER): Fix and rename as... - (AT_TEST_M4): this. - * tests/others.at: Use it. - - * config/gmp.m4 (_AC_LIB_GMP): In order to read the content of a - variable in shell scripts, one uses `$'... - -2001-10-04 Gary V. Vaughan - - * configure.ac: `rm -f $m4_getopt_h' was lost. - -2001-10-04 Gary V. Vaughan - - * configure.ac (TIMESTAMP): Display with AS_BOX at configure - time. Define it for config.h in order to... - * src/main.c (main): ...display the timestamp for --version. - -2001-10-04 Akim Demaille - - * modules/gnu.c (m4_regexp_do, m4_patsubst_do): Extracted from - previous builtins `regexp' and `patsubst'. - (regexp, patsubst): Use them. - (eregexp, epatsubst): New builtins. - * doc/m4.texinfo (Patsubst, Regexp): Rename and complete as... - (Epatsubst and Patsubst, Eregexp and Regexp): these. - (Extensions): More info on REs. - -2001-10-04 Akim Demaille - - * modules/modtest.c (init_handler): Consistently output to stderr. - (finish_handler): New. - (test): The `if' is an `assert'. - * tests/modules.at: Adjust. - -2001-10-04 Akim Demaille - - * m4/utility.c (m4_bad_argc): Detail the mismatches. - -2001-10-01 Akim Demaille - - * tests/generate.awk: Tag the tests with `documentation'. - * tests/modules.at (AT_CHECK_M4_MODTEST): New. - Use the make the existing modtest tests more uniform, and complete - the set of possibilities. - -2001-10-01 Akim Demaille - - * config/gmp.m4: Consult the user before using GMP: use - --without-gmp. - * configure.ac: Adjust. - * modules/gmp.c: No protection needed as the module is not built - if GMP is not used. - -2001-10-01 Akim Demaille - - * tests/generate.awk: Remove debugging code. - (fatal): Specify the current location. - - * m4/debug.c, m4/macro.c, m4/utility.c, modules/format.c, - * modules/gnu.c, modules/m4.c: Use M4ARG. - -2001-10-01 Akim Demaille - - * modules/gnu.c (RE_SYNTAX_BRE, RE_SYNTAX_ERE): New. - (m4_regexp_compile): New. - (regexp, patsubst): Use it. - -2001-09-30 Gary V. Vaughan - - Reinstate the memory handling improvements from the patch I just - reverted. Relevant ChangeLog entries repeated here: - - * m4/module.c (m4_module_remove): New function that holds the core - of the old m4_module_unload. - (m4_module_unload): Use it. - (m4_module_unload_all): When we know the modules will never be - used again (i.e. on exit), free up as much module memory as - possible. There are still some artifacts from resident modules - living inside ltdl.c, but everything else is freed. - * m4/debug.c (m4_debug_exit): Free memory allocated in - m4_debug_init(). - * m4/input.c (m4_input_exit): Ditto wrt m4_input_init(). - * m4/output.c (m4_output_exit): Ditto wrt m4_output_init (). - * src/stackovf.c (stackovf_exit): Ditto wrt setup_stackovf_trap (). - * m4/m4module.h: Updated prototypes. - * m4/hash.c (m4_hash_exit): Free the nodes on the free list. - * m4/hash.h: Updated prototypes. - * src/main.c (main): Use all these new functions to clean up as - much memory as possible before exit. - -2001-09-30 Gary V. Vaughan - - Reverted my large patch for removing the old m4_symbol - structure on 2001-09-20. We are still not happy about the way - trace works in conjunction with defn and undefine, and leaving - the reverted patch active prevents us from moving the traced - bit from the definition back to the symbol. - -2001-09-30 Gary V. Vaughan - - * configure.in: Moved to... - * configure.ac: ...here. Added a libtool like timestamped - banner, and tidied up the libltdl cruft. - * config/mkstamp: Script to extract a timestamp from ChangeLog. - * modules/Makefile.am (INCLTDL): Removed. This is required - only when libltdl is configured in a subdirectory. - * src/Makefile.am: Ditto. - (LIBADD_DL): No need to add this again, libtool already knows - that libm4.la depends on it. - * m4/Makefile.am: Automake sets variables from AC_SUBST. Use - them. - - * TODO: stackovf.c is basically broken. - Reported by Marc Espie - -2001-09-28 Akim Demaille - - * tests/Makefile.am (EXTRA_DIST): `m4' is not to be shipped. - -2001-09-27 Akim Demaille - - * tests/m4.in: Don't use short options. - Simplify the stderr signature normalization. - -2001-09-27 Akim Demaille - - tests/m4 shall be position independent. - - * tests/m4.in: New. - * tests/m4: Remove. - * tests/testsuite.at: No args to AT_INIT. - * configure.in, tests/Makefile.am: Adjust. - -2001-09-22 Akim Demaille - - Autotest has changed again. - - * tests/Makefile.am (DISTCLEANFILES): Add package.m4. - (package.m4): Remove. - * configure.in: Adjust to LIBADD_GMP. - -2001-09-21 Gary V. Vaughan - - * config/gmp.m4 (AC_ARG_WITH): Removed. - (GMP_LIB): Renamed to LIBADD_GMP for consistency. - (AC_LIB_GMP): When performing a test compile against libgmp, - include the header gmp.h if possible, and link against -lgmp. If - they both work define USE_GMP. - * modules/Makefile.am (mpeval_la_LIBADD): Add LIBADD_GMP. - (mpeval_LTX_init_func): Complain on load that there was no libgmp - at compile time. - -2001-09-20 Gary V. Vaughan - - * m4/evalparse.c: Moved to... - * modules/evalparse.c: ...here. This code is shared between - modules/mpeval.c and modules/m4.c, so there is no need to pollute - the libm4 API with its details. Moderately rewritten to interface - into its clients more simply. - * m4/eval.c: Deleted. Migrated functionality to... - * modules/m4.c: ...here. - (builtin_eval): Implemented in terms of the new interface style. - * modules/mpeval.c (builtin_mpeval): Ditto. - * m4/m4module.h: Removed references to the former m4/eval.c. - * m4/Makefile.am (libm4_la_SOURCES): Removed eval.c. - (EXTRA_libm4_la_SOURCES): Deleted. - * modules/Makefile.am (EXTRA_m4_la_SOURCES): Reference evalparse.c. - (EXTRA_mpeval_la_SOURCES): Reference evalparse.c. - -2001-09-20 Akim Demaille - - * config/gmp.m4 (AM_WITH_GMP): Rename as... - (AC_LIB_GMP): this. - By default, use gmp. - Massive revamping. - * configure.in: Adjust. - Use Automake conditionals for USE_GMP. - Always compute sizeof (long long int). - This was a bug BTW, as `eval' (not `mpeval') depends on it: - before, it was used _only_ if mpeval was not activated. - * modules/Makefile.am (pkglibexec2dir, +pkglibexec2_LTLIBRARIES) - (mpeval_la_LIBADD): New macros. - * modules/mpeval.c: No longer be conditioned by WITH_GMP. - Indent. - * tests/Makefile.am ($(srcdir)/$(TESTSUITE)): Create package.m4. - * tests/atlocal.in, tests/builtins.at: Depend upon USE_GMP, not - WITH_GMP. - -2001-09-20 Akim Demaille - - * tests/Makefile.am (package.m4): New. - * tests/testsuite.at: Adjust AT_INIT and AT_VICTIMS. - -2001-09-20 Gary V. Vaughan - - More cleanup. After the last patch, m4_symbol holds nothing but - the head of a chain of m4_token_data. So I have removed the old - m4_symbol, so that m4_token_data chains are stored directly in the - value cell of a hash table node. But there's more... m4_symbol - was a more natural name for the symbol value cell, and now that it - is gone I have renamed the former m4_token_data structure to - m4_symbol. This change turned out to be a pig to get right, since - the original code didn't need to modify the value cell itself, - since changing the chain happened inside the m4_symbol that used - to be returned -- I had to pass the address of the value cell - across various function calls, incase the head value changed. I - also tightened up the memory management to help me find a nasty - memory corruption bug that took me all night to track down... - - * m4/m4private.h (struct m4_symbol): Removed. - (struct m4_token_data): Renamed to `struct m4_symbol'. Updated - all references. - * m4/hash.c (m4_hash_iterator_value): Return the address of the - value cell. Updated all callers. - * m4/symtab.c: Took advantage of the simplification in the data - structures to rewrite a lot of this file more simply. There is - still some room for optimisation here, but we should tackle that - systematically closer to the release. - - * m4/ltdl.c: Added dmalloc support, and fixed some memory leaks it - revealed. This version is ahead of CVS libtool until I get chance - to flush my changes. - * m4/module.c (m4_module_remove): New function that holds the core - of the old m4_module_unload. - (m4_module_unload): Use it. - (m4_module_unload_all): When we know the modules will never be - used again (i.e. on exit), free up as much module memory as - possible. There are still some artifacts from resident modules - living inside ltdl.c, but everything else is freed. - * m4/debug.c (m4_debug_exit): Free memory allocated in - m4_debug_init(). - * m4/input.c (m4_input_exit): Ditto wrt m4_input_init(). - * m4/output.c (m4_output_exit): Ditto wrt m4_output_init (). - * src/stackovf.c (stackovf_exit): Ditto wrt setup_stackovf_trap (). - * m4/m4module.h: Updated prototypes. - * m4/hash.c (m4_hash_exit): Free the nodes on the free list. - * m4/hash.h: Updated prototypes. - * src/main.c (main): Use all these new functions to clean up as - much memory as possible before exit. - -2001-09-18 Gary V. Vaughan - - The `traced' flag needs to be attached to the definition of a - symbol rather than the current symbol containing the definition. - Implementing this showed up some long standing post 1.4 bugs in - flag propogation which I also fixed. - - * m4/m4private.h (struct m4_symbol): Remove the traced flag. - (struct m4_token_data): And add it back in here. - * m4/input.c (init_macro_token): Propogate the traced flag - correctly. - * m4/macro.c (expand_argument): Ditto. - * tests/builtins.at (trace2, trace3): New tests based on Akim's - sadistic email ;-) - -2001-09-08 Gary V. Vaughan - - * m4/m4private.h (struct m4_token_data): Simplified by removing - the redundant `traced' flag, and one level of structure nesting. - (M4_TOKEN_DATA_FUNC_TRACED): Removed. - * m4/input.c (init_macro_token): No need to initialise removed - `traced' field. - * m4/macro.c (expand_argument): No need to copy it either. - * m4/utility.c (m4_token_data_func_traced): Or provide an access - function. - - * m4/hash.c (m4_hash_bucket_insert): Symbol shadowing is no longer - dependant on multiple symbols with the same key, so preserving - relative symbol order in each bucket during resizing is no longer - required. The resize function is considerably faster as a result. - - * m4/m4module.h, m4/builtin.c, m4/symtab.c: - s/m4_symbol_insert/m4_symbol_define/g; - s/m4_builtin_insert/m4_builtin_define/g; - s/m4_macro_insert/m4_macro_define/g. Updated all callers. - -2001-09-08 Gary V. Vaughan - - Get rid of m4_symbol_lookup_t entirely. With Akim's earlier - commits, the m4_lookup_symbol dispatch function is split into - specialised functions that must be called directly. - - * m4/m4module.h (m4_symbol_lookup_t): Removed. - * m4/symtab.c (m4_lookup_symbol): Removed. - (m4_symbol_builtin, m4_symbol_macro): New functions. - * m4/builtin.c (m4_builtin_define): Split into... - (m4_builtin_pushdef, m4_builtin_insert): ...these. - (m4_macro_define): Split into... - (m4_macro_pushdef, m4_macro_insert): ...these. - * src/main.c (main): Set command line macros from `-D' parameters - using `m4_macro_define'. - -2001-09-08 Gary V. Vaughan - - * m4/symtab.c (m4_symtab_remove_module_references): Renamed as - this from m4_remove_table_reference_symbols(). - * m4/m4module.h, m4/module.c: Updated all references. - -2001-09-07 Akim Demaille - - * modules/stdlib.c, modules/times.c: Misc cleanups. - -2001-09-07 Akim Demaille - - * configure.in: We now need Autoconf 2.52e. - * m4/m4module.h (m4_symbol_lookup_t): Remove `M4_SYMBOL_POPDEF' - and `M4_SYMBOL_DELETE'. - * m4/symtab.c (m4_lookup_symbol, symtab_debug): Adjust. - * src/main.c (main): Adjust. - -2001-09-06 Gary V. Vaughan - - Fix the obstack.h problem once and for all! At configure time we - can test for a system supplied obstack.h: depending on the - result, we now generate system.h with an #include of the correct - header. As a bonus, I've also added a --with-included-obstack, - incase the user doesn't like the system obstack for some - reason... and also we can test the shipped obstack on a system - that has oe of its own. We also now need to be careful to add - build directories to the include search path, since the generated - system.h will be in the build tree. - - * configure.in (AC_CONFIG_FILES): Generate system.h from - system-h.in. - * config/gnu-obstack.m4 (M4_AC_FUNC_OBSTACK): Determine whether to - include the system obstack header or the copy shipped with M4. - Allow the user to override configure and force the build to use - the shipped version. - * m4/system-h.in: New file, template for... - * m4/system.h: ...this. Now deleted. - * m4/m4module.h: Include system.h before everything else. - * src/freeze.c: Ditto. - * m4/Makefile.am (dist-hook): Remove generated system.h. - (INCLUDES): Check builddir for generated headers before checking - srcdir. - * modules/Makefile.am (INCLUDES): Ditto. - * src/Makefile.am (INCLUDES): Ditto. - -2001-09-05 Gary V. Vaughan - - * TODO: Remove the items that have been addressed already. - -2001-09-05 Akim Demaille - - * src/main.c (main): Standardize --version. - -2001-09-05 Akim Demaille - - * modules/format.c (format): Have a bigger `str'. - -2001-09-05 Akim Demaille - - Rationalize warnings, reporting the macro name as if it were a - program name, and assertions. - - * m4/m4module.h (m4_lookup_symbol): Prototype, it is still used. - (M4WARN): New. - * m4/symtab.c (m4_lookup_symbol, m4_symbol_popdef) - (m4_symbol_delete): - Use assert for internal errors. - * m4/utility.c (m4_bad_argc, m4_numeric_arg, m4_dump_symbols): Use - M4WARN. - * modules/m4.c (undefine, defn, traceon, traceoff, dumpdef): use - M4WARN and assert. - * tests/builtins.at (pushpop): Adjust. - -2001-09-05 Akim Demaille - - * m4/symtab.c (m4_symbol_insert): Don't use `foo () || bar ()' - with pointers. - -2001-09-05 Akim Demaille - - * m4/m4module.h (m4_symbol_lookup): Remove M4_SYMBOL_LOOKUP. - * m4/macro.c, m4/symtab.c: Adjust. - -2001-09-05 Akim Demaille - - * m4/symtab.c (m4_symbol_popdef, m4_symbol_delete): Rename as... - (m4_symbol_pop, m4_symbol_del): this. - (m4_symbol_lookup, m4_symbol_pushdef, m4_symbol_insert) - (m4_symbol_popdef, m4_symbol_delete): New. - (m4_lookup_symbol): Adjust. - * m4/m4module.h, src/main.c, modules/gnu.c, modules/m4.c: Adjust. - -2001-09-05 Akim Demaille - - * m4/m4module.h (m4_symbol_lookup): Rename as... - (m4_symbol_lookup_t): this. - -2001-09-05 Akim Demaille - - * m4/m4module.h (m4_symbol_lookup): Remove M4_SYMBOL_IGNORE, - unused. - * m4/symtab.c (m4_lookup_symbol): Adjust. - -2001-09-03 Gary V. Vaughan - - Bootstrap will now work with Libtool 1.4.1 or higher: - * bootstrap: Remove stale autom4te.cache files when - rebootstrapping. - * config/Makefile.am (ACLOCAL_MACROS): Add ltdl.m4 and - libtool.m4. - * bootstrap: Ignore acinclude.m4 now the we include ltdl.m4 and - libtool.m4 directly. - Run libtoolize to refresh ltmain.sh. - * config/ltmain.sh: Deleted. - * acinclude.m4: Deleted. - * m4/ltdl.c, m4/ltdl.h: Updated from libtool-1.4.1. - - * config/debug.m4 (AC_LIBTOOL_COMPILER_OPTION): Provide a fallback - implementation for the cvs impaired libtool user. - -2001-09-03 Akim Demaille - - * m4/symtab.c (m4_lookup_symbol): Give more details when reporting - internal errors. - Avoid using `default' in switch, as it hides useful compiler - warnings when a case is forgotten. - -2001-09-03 Akim Demaille - - * src/main.c (MODULE_SHORTOPT, MODULEPATH_SHORTOPT): Remove, there - is no such thing as `WITH_MODULES'. - -2001-09-03 Akim Demaille - - Improve the test suite's selfcontainedness. - - * doc/m4.texinfo: Let `input.m4' be the input file, not `in'. - (Include, Undivert): Tag the other input files. - * tests/generate.awk: Catch `@comment file:'. - `-I $src' is no longer needed. - `next' is really like `return': the rest is skipped. - Adjust to `input.m4'. - (fatal): New function. - * tests/foo, tests/incl.m4: Remove. - -2001-09-01 Gary V. Vaughan - - The shadowing mechanism and, infact, the whole symbol table - implementation was creaking under the weight of the features piled - on top of it. We now have a separate hash table module which will - dynamically resize to keep symbol density withing good performace - limits, and a new symtab module layered above it. Symbol lookups - are now marginally more efficient (since the shadowed flag is no - longer required) and symbol removal, such as on module unload, is - considerably faster due to a reorganisation of the data structures - used in symtab.c. - - * src/main.c (main): Don't mention `-H'. - * doc/m4.texinfo (Invoking m4): Document that -H no longer has any - effect. - * NEWS: Updated. - * m4/hash.c: New generalised dynamic hash table data structure - management module. - * m4/hash.h: Public interface. - * m4/Makefile.am (pkginc_HEADERS): Add hash.h. - (libm4_la_SOURCES): Add hash.c. - * m4/symtab.c: More or less rewritten from scratch, within the - bounds of the previous API. - (m4_symtab_apply): A cleaner version of the old hack_all_symbols - call. Updated all callers. - * m4/m4module.c: #include , and changed all affected - declarations to reflect API changes. - (M4INIT): Generate a declaration too, to avoid the warning with - --enable-debug builds. - (M4FINISH): Ditto. - (HASHMAX): Removed. - * m4/utility.c (hash_table_size): Removed. - (m4_dump_symbols): Rewritten to build and qsort an array of symbol - names, which are then looked up by builtin_dumpdef() as necessary. - This implies a small speedup in builtin_symbols(), which discarded - all of the symbol info under the old call. - * m4/m4private.h (m4_symbol): Removed shadowed flag -- symbol - shadowing is implicit in respect to the new data structures. - symbol names are no longer duplicated here, they are stored in the - key field of the hash table. - Moved macro_args and blind_no_args... - (m4_token_data): ...to here. - m4/macro.c (expand_macro): Added a name argument since the symbol - name is no longer copied into each struct m4_symbol. Modified all - callers. - (collect_arguments): Ditto. - * modules/m4.c (set_trace): Ditto. - * modules/gnu.c (builtin_symbols): Updated. - * src/freeze.c (produce_symbol_dump): Much improved in light of - the improved symbol table layout. - -2001-09-01 Gary V. Vaughan - - * m4/m4private.h (SYMBOL_NEXT): Move into m4's name space; renamed - to M4_SYMBOL_NEXT. - (SYMBOL_TRACED): Similarly renamed by prefixing with `M4_'. - (SYMBOL_SHADOWED, SYMBOL_MACRO_ARGS, SYMBOL_BLIND_NO_ARGS, - SYMBOL_NAME, SYMBOL_TYPE, SYMBOL_TEXT, SYMBOL_FUNC, - SYMBOL_HANDLE): Ditto. - * m4/builtin.c, m4/macro.c, m4/symtab.c, m4/utility.c, - modules/gnu.c, modules/m4.c, src/freeze.c, - src/main.c: Updated all references. - - * src/Makefile.am (m4_SOURCES): Don't list $(M4OBJS) here, since - Automake 1.5 chokes on dynamic source file lists, Besides, it is - already listed in m4_LDADD... how did that ever used to work? - * configure.in (getopt.h): Use AC_CONFIG_LINKS instead of a manual - link. - * config/gnu-obstack.m4 (M4_AC_FUNC_OBSTACK): Ditto. - Suggested by Tim Van Holder - - * tests/m4: Don't call the m4 wrapper script with libtool, it - works fine all by itself. - -2001-08-30 Gary V. Vaughan - - The experimental `changeword' feature never took off, and has - no obvious advantages over `changesyntax' to compensate the - enormous speed penalty it carries: - * configure.in (ENABLE_CHANGEWORD): Removed. - * m4/m4module.h (m4_set_word_regexp): Removed. - * m4/m4private.h (m4_token_data): Removed original_text field. - * m4/utility.c (m4_token_data_orig_text): Removed. - * m4/input,c: Removed all conditional ENABLE_CHANGEWORD code. - * m4/macro.c: Ditto. - * src/main.c: Ditto. - * modules/Makefile.am (changeword.la): Removed. - * modules/changeword.c: File removed. - * doc/m4.texinfo: References to changeword and --word-regexp - removed. - * po/POTFILES.in: modules/changeword.c removed. - * tests/atlocal.in (ENABLE_CHANGEWORD): Removed. - * tests/builtins.at (changeword): Test removed. - -2001-08-30 Akim Demaille - - * bootstrap.sh: Create aclocal.m4 instead of modifying it. - This also help having a single list of m4 files: in - config/Makefile.am. - * config/Makefile.am (STANDARD_MACROS): Rename as... - (ACLOCAL_MACROS): this. - (list-standard-macros): Remove. - (spy): New. - -2001-08-29 Gary V. Vaughan - - In an attempt to moderate my egomania... - * tests/modules.at: Remove attributions. - - * tests/generate.awk: When making substitutions to "@&t@", either - "&" or "\&" in the substitution string argument to gsub refer back - to the matched text. "@\\&t@" seems to work though, Tests 43 and - 67 now pass for me. - -2001-08-29 Akim Demaille - - * tests/others.at (changeword, ddivert, debug, esyscmd, exp, gmp) - (include, indir, multiquotes, patsubst, pushdef/popdef, regexp) - (sync-lines, trace, translit, undivert, wrap): Move to... - * tests/builtins.at: this new file. - * tests/others.at (Discard comments, import-environment): Move to... - * tests/options.at: this new file. - -2001-08-29 Akim Demaille - - * tests/others.at (Freezing modules) - (--module-directory: absolute path, modpath2, modpath3) - (M4MODPATH: absolute path, modtest, shadow, unload): Move to... - * tests/modules.at: here, new file. - * tests/others.at, tests/generate.awk: Add a banner. - * tests/testsuite.at: Adjust. - (AT_CHECK_M4_FILTER): New, but unused. - -2001-08-29 Akim Demaille - - * tests/testsuite.at (AT_CHECK_M4): Don't pass -I, let the tests - handle that. - * tests/others.at (wrap): Inline wrap.m4. - (shadow): Inline shadow.m4. - (iso8859): Don't specify the path from top_srcdir, but from srcdir. - * tests/m4: Simplify. - -2001-08-29 Akim Demaille - - * tests/Makefile.am ($(srcdir)/$(TESTSUITE)): Use autom4te's - --language. - -2001-08-29 Akim Demaille - - * tests/generate.awk (normalize): s/@__@/@&t@/. - -2001-08-28 Akim Demaille - - * examples/indir.m4, tests/others.at (indir): s/nonsens/nonsense/. - -2001-08-28 Gary V. Vaughan - - * bootstrap (generate.awk): Generate test cases with new script. - -2001-08-27 Akim Demaille - - * tests/Makefile.am (installcheck-local): Don't use - `dc_install_base' which is not visible here, but `exec_prefix' - which is clearly the RT anyway. - * tests/testsuite.at (AT_CHECK_M4): Don't pass -M here since it is - related to testing a now installed m4. - * tests/m4: Do it here. - -2001-08-27 Akim Demaille - - * tests/others.at (indir): Formatting change. - -2001-08-27 Akim Demaille - - * tests/Makefile.am (installcheck-local): New. - * tests/testsuite.at (AT_CHECK_M4): Pass `-b' so that C-c works on - the test suite. - Prefer options over envvars. - * src/main.c (main): First bug caught by the test suite (yeah!): - --batch lacked a `break' which resulted in an accidental - invocation of --discard-comments. - -2001-08-27 Akim Demaille - - * tests/others.at (capitalize, changeword, comments, ddivert) - (debug, esyscmd, exp, foreach, forloop, fstab, hanoi, include) - (misc, multiquotes, patsubst, pushdef/popdef, regexp, reverse) - (sysv-args, trace, translit, undivert): Don't rely on files in - examples/: AT_DATA them. - -2001-08-27 Akim Demaille - - Let the test suite use a wrapper around the not installed m4 to - pretend it is (installed). - - * bootstrap (aclocal.m4): Output AC_SUBST's and AM_CONDITIONAL's in - such a way that m4 does not process them. - * configure.in: The package name seems to be `m4', not `M4'. - * tests/m4: New. - * tests/atlocal.in (at_package, M4): Remove. - * tests/testsuite.at, tests/others.at: Use m4, not $M4. - -2001-08-27 Akim Demaille - - * tests/Makefile.am (CLEANFILES): Remove. - (DISTCLEANFILES, clean-local): New. - * examples/mktests.sh: Remove. - -2001-08-27 Akim Demaille - - * Makefile.am (AUTOMAKE_OPTIONS): 1.5. - Don't use aclocal: it's written by hand. - * aclocal.m4: m4_include all the files instead of being built by - aclocal. - * bootstrap: Help automake find the AC_SUBSTs and AM_CONDITIONALs - until it reads the traces by itself. - * configure.in: Require Autoconf 2.42c as we are now using - AC_CONFIG_TESTDIR instead of AT_CONFIG. - Catch unexpanded `jm_' macros. - * config/atconfig.m4: Remove. - * config/error.m4: new. - * config/Makefile.am: Ship the files included by aclocal.m4. - * tests/Makefile.am (TESTSUITE_SOURCES): Rename as... - (TESTSUITE_AT): this, to please Automake. - (TESTSUITE): This target uses autotest/autotest.m4, not - autotest/general.m4. - * tests/testsuite.at: Prereq Autotest 2.52c. - * examples/Makefile.am (pkgdata_DATA): Rename as... - (dist_pkgdata_DATA): this. - * doc/Makefile.am (man_MANS): Rename as... - (dist_man_mans): this. - -2001-08-20 Gary V. Vaughan - - * m4/system.h [cygwin*]: Thanks to Paul Sokolovsky and - Robert Collins, building on Cygwin no longer requires Windows - import and export symbol decorations. - * m4/m4module.h (M4_SCOPE) [cygwin*]: Deleted all occurences. - * m4/error.h (M4_SCOPE) [cygwin*]: Ditto. - * m4/debug.c (M4_GLOBAL_DATA) [cygwin*]: Ditto. - * m4/error.c (M4_GLOBAL_DATA) [cygwin*]: Ditto. - * m4/input.c (M4_GLOBAL_DATA) [cygwin*]: Ditto. - * m4/macro.c (M4_GLOBAL_DATA) [cygwin*]: Ditto. - * m4/output.c (M4_GLOBAL_DATA) [cygwin*]: Ditto. - * m4/utilty.c (M4_GLOBAL_DATA) [cygwin*]: Ditto. - * m4/xmalloc.c (M4_GLOBAL_DATA) [cygwin*]: Ditto. - * configure.in (LIBM4_DLL_IMPORT) [cygwin*]: Don't set this - anymore. - * src/Makefile.am (AM_CPPFLAGS) [cygwin*]: Don't use it either! - * modules/Makefile.am (AM_CPPFLAGS) [cygwin*]: Ditto. - -2001-08-20 Gary V. Vaughan - - Ansify the source. Previously we had a mix, where my code was - in a K&R compatible style, and the preexisting code was in ANSI - style. Nothing is lost wrt release 1.4 by reverting to ANSI, - and now the code base is much cleaner. - - * m4/system.h: Remove M4_PARAMS macro and all users. Remove - VOID macro and all users. - * m4/m4module.h: Ansify function prototypes and headers. - * m4/builtin.c: Ditto. - * m4/evalparse.c: Ditto. - * m4/input.c: Ditto. - * m4/macro.c: Ditto. - * m4/module.c: Ditto. - * m4/output.c: Ditto. - * m4/path.c: Ditto. - * m4/symtab.c: Ditto. - * m4/utility.c: Ditto. - * modules/format.c: Ditto. - * modules/gnu.c: Ditto. - * modules/m4.c: Ditto. - * modules/mpeval.c: Ditto. - * src/freeze.c: Ditto. - * src/m4.h: Ditto. - * src/main.c: Ditto. - -2001-08-20 Akim Demaille - - * config/atconfig.m4: s/EOF/ATEOF/, so that configure can be - generated with stock 2.52. - -2001-08-20 Akim Demaille - - * config/atconfig.m4: New, until part of Autoconf per se. - * configure.in (AT_CONFIG): Use it. - Adjust. - * tests/mkconfig.sh, tests/atconfig.in, tests/defs: Remove. - * tests/atlocal.in: New. - * tests/generate.awk: For the time being, the empty quadrigraph is - `@__@'. - * tests/others.at (changeword, gmp): Check the configuration - variable against `yes'. - * tests/testsuite.at (dnl): Allow it, as it's used all over the - place. - -2001-08-20 Akim Demaille - - * m4/utility.c (m4_numeric_arg): Spell out the culprit. - * modules/m4.c (undivert): Disable the possibility of undiverting - several files at once: it is not documented, it is inconsistent - with the other macros, it can be straightforwardly mocked by - several invocations, and most importantly, it prevents the - possibility of other kinds of extension. - Use `m4_numeric_arg'. - -2001-08-20 Akim Demaille - - * examples/include.m4: Typo. - * tests/generate.awk: Really add it. - * tests/Makefile.am: Adjust. - * tests/others.at (Discard comments): It sure fails without `-c'. - (include, undivert): Add -I examples/. - -2001-08-20 Akim Demaille - - Use sprintf, not ecft and friends since it is standard, portable, - simplifies the code, and since the latter is even deprecated - according to the GNU libc documentation. - - * modules/format.c: Drop evct support. - -2001-08-19 Gary V. Vaughan - - * config/debug.m4 (M4_AC_CHECK_DEBUGGING): Cleaned up. Don't test - for `-pipe' here... - * configure.in: ...do it here instead. - - * c-boxes.el: Deleted. - * m4/builtin.c: Reformat box comments to be closer to GNU - standards. - * m4/debug.c: Ditto. - * m4/eval.c: Ditto. - * m4/evalparse.c: Ditto. - * m4/input.c: Ditto. - * m4/m4module.h: Ditto. - * m4/macro.c: Ditto. - * m4/output.c: Ditto. - * m4/symtab.c: Ditto. - * m4/utility.c: Ditto. - * modules/changeword.c: Ditto. - * modules/format.c: Ditto. - * modules/gnu.c: Ditto. - * modules/load.c: Ditto. - * modules/m4.c: Ditto. - * modules/modtest.c: Ditto. - * modules/mpeval.c: Ditto. - * modules/perl.c: Ditto. - * modules/shadow.c: Ditto. - * modules/stdlib.c: Ditto. - * modules/time.c: Ditto. - * src/freeze.c: Ditto. - * src/main.c: Ditto. - -2001-08-17 Gary V. Vaughan - - * m4/module.c: Fixup some errors in the description comment. - -2001-08-17 Akim Demaille - - * tests/others.at (iso8859): Specify the path to the M4 test file. - * tests/testsuite.at (AT_CHECK_M4): Normalize the path of input - files in error messages. - -2001-08-17 Akim Demaille - - * tests/testsuite.at (AT_CHECK_M4): Anchor M4PATH in $top_srcdir. - * tests/others.at: Adjust input files paths. - * tests/atconfig.in: Set top_builddir. - * tests/Makefile.am: Adjust. - `testsuite' is in src, not build. - -2001-08-17 Akim Demaille - - * tests/Makefile.am (EXTRA_DIST): Ship generate.awk. - (generate.at): Install a temporary hack until the actual - generate.awk is added to the repository. - * tests/atconfig.in: New. - -2001-08-17 Akim Demaille - - Really apply the patch ``Drop Autoconf 2.13 compatibility.'' - -2001-08-17 Akim Demaille - - * doc/m4.texinfo: Promote proper quotation. - -2001-08-17 Akim Demaille - - Remove the non Autotest tests. - - * tests/other-tests/capitalize.test, - * tests/other-tests/changeword.test, - * tests/other-tests/comments.test, tests/other-tests/ddivert.test, - * tests/other-tests/debug.test, - * tests/other-tests/discard-comments.m4, - * tests/other-tests/discard-comments.test, - * tests/other-tests/esyscmd.test, tests/other-tests/exp.test, - * tests/other-tests/foreach.test, tests/other-tests/forloop.test, - * tests/other-tests/frozen.m4, tests/other-tests/fstab.test, - * tests/other-tests/gmp.m4, tests/other-tests/gmp.test, - * tests/other-tests/hanoi.test, - * tests/other-tests/import-environment.m4, - * tests/other-tests/import-environment.test, - * tests/other-tests/include.test, tests/other-tests/indir.test, - * tests/other-tests/iso8859.m4, tests/other-tests/iso8859.test, - * tests/other-tests/misc.test, tests/other-tests/modfreeze.test, - * tests/other-tests/modpath1.test, tests/other-tests/modpath2.test, - * tests/other-tests/modpath3.test, tests/other-tests/modpath4.test, - * tests/other-tests/modtest.test, - * tests/other-tests/multiquotes.test, - * tests/other-tests/patsubst.test, tests/other-tests/pushpop.test, - * tests/other-tests/regexp.test, tests/other-tests/reverse.test, - * tests/other-tests/shadow.test, tests/other-tests/stackovf.test, - * tests/other-tests/sync-lines.m4, - * tests/other-tests/sync-lines.test, - * tests/other-tests/sysv-args.test, tests/other-tests/trace.test, - * tests/other-tests/translit.test, tests/other-tests/undivert.test, - * tests/other-tests/unfrozen.m4, tests/other-tests/unload.test, - * tests/other-tests/wrap.test: Remove. - - * tests/run-test, tests/get-them: Remove. - * tests/Makefile.am: Adjust. - -2001-08-17 Akim Demaille - - others.at no longer depends on other-tests/. - - * tests/others.at (stackovf): You're actually... - (sync-lines): this. - (modfreeze, modpath1, modpath2, modpath3, modpath4, modtest, shadow) - (unload.test): Keep their authorship. - (discard-comments, gmp, import-environment, modfreeze) - (sync-lines): Embed the input files. - * tests/stackovf.test: Copy from other-tests/stackovf.test. - * tests/iso8850.m4: Copy from other-tests/iso8859.m4. - -2001-08-17 Akim Demaille - - * doc/m4.texinfo (Esyscmd): Fix the paths in the Vice example. - (M4exit): Tag the exit status of the example. - * tests/get-them: Adjust. - * tests/generate.awk: New, based on get-them. - * tests/Makefile.am: Adjust to generate `generated.at'. - * tests/testsuite.at: Adjust. - (AT_CHECK_M4): Don't overquote. Blush... - -2001-08-17 Akim Demaille - - Start using Autotest. atconfig creation is still lacking. - - * examples/patsubst.m4, modules/modtest.m4, modules/shadow.m4, - * examples/reverse.m4, tests/other-tests/import-environment.m4, - * tests/other-tests/iso8859.m4: Don't produce trailing blanks. - * tests/other-tests/import-environment.test: Don't check LANGUAGE - as it might be `unset', or set to `C'. - * tests/other-tests/iso8859.test, tests/other-tests/modpath1.test, - * tests/other-tests/modpath2.test, tests/other-tests/modpath3.test, - * tests/other-tests/modpath4.test, tests/other-tests/modtest.test, - * tests/other-tests/patsubst.test, tests/other-tests/reverse.test, - * tests/other-tests/shadow.test: Adjust. - * tests/testsuite.at, tests/others.at: New. - * tests/Makefile.am: Adjust. - -2001-08-17 Akim Demaille - - Drop Autoconf 2.13 compatibility. - - * configure.in (changeword): No need to undefine it, as anyway if - it's defined, M4sugar moved it as m4_changeword. - And anyway, proper quotation is enough. - (m4_pattern_allow): As it exists in 2.50, just use it. - (AC_OUTPUT): Split in AC_CONFIG_FILES and AC_CONFIG_COMMANDS. - Don't handle Gettext's duties, let it handle them. - * config/gnu-obstack.m4: Use m4_pattern_allow directly. - -2001-08-17 Akim Demaille - - * modules/m4.c (m4_dumpdef): Output to stderr, not m4_debug. - (m4_errprint): Use fputs. - * doc/m4.texinfo (Invoking m4) <--error-output>: errprint and - dumpdef are not concerned. - (Dumpdef, Errprint): Emphasize their insensitivity to - --error-output. - * doc/Makefile.am: Add `TAGS' support. - (MAINTAINERCLEANFILES): Remove texinfo.tex and mdate-sh which are - in `config/' now. - * config/Makefile.am (MAINTAINERCLEANFILES): New. - -2001-08-17 Akim Demaille - - * modules/Makefile.am (ETAGS_ARGS): New. - -2001-08-17 Akim Demaille - - * m4/symtab.c (m4_hack_all_symbols, m4_lookup_symbol): Formatting - changes. - -2001-08-17 Akim Demaille - - * m4/builtin.c (m4_macro_define): Do not reset SYMBOL_TRACED. - -2001-08-17 Akim Demaille - - * m4/m4module.h (m4/list.h): Don't include it. - -2001-08-16 Gary V. Vaughan - - m4_modules are no more, we use lt_dlhandles directly and let - latest libltdl features manage the list of loaded modules. - * acinclude.m4: Regenerated. - * m4/ltdl.c: Updated from master copy. - * m4/module.c: Reimplemented to take advantage of advances in - libltdl. - * m4/builtin.c (m4_builtin_find_by_name): Traverse loaded module - list with lt_dlhandle_next. - (m4_builtin_find_by_func): Ditto. - (m4_builtin_table_install): Use lt_dlhandle. - (m4_macro_define): Ditto. - (m4_macro_table_install): Ditto. - m4/module.h: Prototype new module management API. - (m4_modules): No longer required. - (m4_module_init_t, m4_module_finish_t): POSIX namespace - violations, renamed to... - (m4_module_init_func, m4_module_finish_func): ...these, - respectively. - (M4INIT_HANDLER): Clean way to declare init functions in modules. - (M4FINISH_HANDLER): And similarly for finish functions. - * m4/system.h (_CONC): Used by M4INIT_HANDLER and M4FINISH_HANDLER - -- Add indirection to the CONC macro so that arguments are - correctly expanded. - * modules/modtest.c (m4_init_module): Replaced with M4INIT_HANDLER. - * modules/shadow.c (m4_init_module): Ditto. - Due to new init function semantics, be careful to perform the - initialisation only on first load. - * modules/perl.c (m4_init_module): Ditto. And Ditto. - (m4_finish_module): Replaced with M4FINISH_HANDLER. - Due to new finish function semantics, be careful to perform the - finalisation only on first load. - * m4/m4private.h (m4_module): Removed in favour of... - (m4_module_data): ...structure without all the wrapper fields. - Instances of this new structure are stored associated lt_dlhandles - with lt_dlcaller_data_set(). - * m4/builtin.c (m4_builtin_define): Takes a handle argument - instead of the old module argument. - (m4_builtin_table_install): Ditto. - * modules/load.c (m4_resident_module): Removed. This is no - longer implemented as a magic symbol... - * modules/m4.c (m4_resident_module): Ditto. - * modules/load.c (M4INIT_HANDLER): ...the module init function now - uses the ltdl api to make the module resident. - * modules/m4.c (M4INIT_HANDLER): Ditto. - * modules/load.c (builtin_modules): Traverse the loaded module - list with lt_dlhandle_next. - (builtin_load): Much simplified in light of the reimplemented - module loader. - * src/freeze.c (produce_module_dump): Cleaned up and optimised in - light of the m4/module.c rewrite. - (produce_symbol_dump): Ditto. - (reload_frozen_state): Ditto. - * m4/list.c, m4/list.h: Files deleted. No longer required. - * m4/Makefile.am (pkginc_HEADERS): Delete list.h reference. - (libm4_la_SOURCES): Delete list.c reference. - * m4/m4private.h (m4_token_data): Add a handle field. This - eliminates many of the searches to find the handle associated with - various tokens that are passed between functions. - (struct m4_symbol): Removed the module field. The - module association does not belong with the symbol... - * m4/input.c (struct m4_builtin): ...it belongs with the builtin - that the module implementation code is from. Added a handle - field. - (m4_push_macro): Add a `handle' argument. Changed all callers. - (init_macro_token): Set the `handle' field for the - m4_token_data. - * m4/macro.c (expand_argument): Copy the new handle field during - reassignment. - * modules/m4.c (macro_install): Use the new handle field to - optimise the search for the correct builtin structure, and pass - the handle details to m4_builtin_define. - -2001-08-15 Akim Demaille - - * config/gnu-obstack.m4 (M4_AC_FUNC_OBSTACK): Be sure `m4/' exists - when creating `m4/obstack.h'. - * tests/Makefile.am (TESTS_ENVIRONMENT): Pass top_srcdir and - top_builddir. - * tests/defs: Make them absolute. - (CDPATH) Neutralize. - * tests/gethem: Use them. - -2001-08-14 Gary V. Vaughan - - * config/ltmain.sh: Doh! Import again for a quoting fix that - prevented any regression test from passing. - - * m4/m4module.h (obstack.h): Choose between installed version - and shipped version based on configure tests. - * src/freeze.c (obstack.h): Ditto. - - * acconfig.h: Removed. No longer required. - - * bootstrap: Rewritten to play nicely with Autoconf 2.5x. - * configure.in (MY_NAME, MY_VERSION): Define these once, and feed - them to AC_INIT and AM_INIT_AUTOMAKE. - * Makefile.am (AUTOMAKE_OPTIONS): Remove `gnits' which would - disallow MY_NAME and MY_VERSION arguments to AM_INIT_AUTOMAKE. - * config/gnu-obstack.m4 (M4_AC_FUNC_OBSTACK): Don't choke on - shell variable m4_cv_func_obstack_h. - * tests/defs (M4): Be more careful about relative path to libtool - script and m4 binary by using $srcdir. - - * src/main.c (main): Use lt_dlinsertsearchdir to prepend -M - optargs to the existing libltdl search path. - * acinclude.m4: Regenerate from latest libtool,m4 and ltdl.m4. - * m4/ltdl.c: Updated. - * m4/ltdl.h: Ditto. - * config/ltmain.sh: Ditto. - -2001-08-11 Gary V. Vaughan - - * src/main.c (main): Add `-b' (for `batch') mode switch to force - interactive mode off. - -2001-08-10 Akim Demaille - - * configure.in: Require Autoconf 2.52. - (AC_ARG_PROGRAM): Remove, handled by Automake. - (m4_getopt): Rename as... - (m4_getopt_h): this. - Allow the tokens `m4_cv_*', `m4_top_srcdir', and `m4_getopt_h'. - Undefine `changeword' only if defined. - * config/gnu-obstack.m4: Require Autoconf 2.52. - (M4_AC_FUNC_OBSTACK): Rename `m4_obstack' and `m4_obstack_h'. - Allow this token. - -2001-08-09 Yuji Minejima - - * doc/m4.texinfo: Fix some typos, and apply some small - clarifications. - -2001-08-09 Andreas Schwab - - * src/main.c (main): Fix improper uses of error (missing format - string). - -2001-08-07 Akim Demaille - - Improve `make distcheck'. - - * configure.in: Be sure to be able to run `mkconfig.sh' when src - != build. - * Makefile.am (dist-hook): Remove, as it is no longer needed. - * doc/m4.texinfo (Include): Add missing blank. - * m4/Makefile.am (EXTRA_DIST): Distribute gnu-obstack.h and - obstack.c. - -2001-08-07 Akim Demaille - - * m4/evalparse.c: A better introductory comment. - * m4/m4module.h (M4_DEBUG_PRINT2): s/M4_debug/m4_debug/. - * m4/macro.c: Adjust old comments. - * modules/README: Typo. - -2001-08-07 Akim Demaille - - * config/gnu-obstack.m4: New. - -2001-08-07 Akim Demaille - - * config/Makefile.am, config/stackovf.m4: New. - * configure.in, Makefile.am: Adjust. - -2001-08-05 gettextize - - * po/Makefile.in.in: Upgrade to gettext-0.10.39. - * po/cat-id-tbl.c: Remove file. - * po/stamp-cat-id: Remove file. - -2001-04-08 Roderick Koehle - - * modules/format.c (format): Formatting for %f was not - interpreting the position of the decimal point correctly for - whole numbers. - -2000-12-01 Gary V. Vaughan - - * TODO: Removed m4exit bug. - * modules/load.c (m4_resident_module): Make this module resident. - * module/m4.c (m4_resident_module): Ditto. - * m4/modules.c (m4_module_load): Use new ltdl resident modules - feature to mark modules as resident if they export - `m4_resident_module' as TRUE. - (m4_module_unload): Do not remove resident modules, and take care - with symbol insertion and deletion with resident modules. - * m4/ltdl.c, m4/ltdl.h: Update to latest unreleased versions to - use resident modules feature. - -2000-11-30 Gary V. Vaughan - - * TODO: Updated. Removed some cruft that has since been fixed - or implemented. Added some more entries. - * NEWS: Updated. - * README: Updated. - * modules/README: Updated. - * doc/m4.texinfo: Updated. - - * modules/gnu.c (builtin_functions): Make indir orthogonal to - builtin, in that each is recognised as a macro only with parameters - (builtin_indir): Passing 0 arguments is now an error, as with - builtin. - - * src/main.c (usage): Added missing description of `-c' option. - -2000-11-29 Gary V. Vaughan - - Consolidate the myriad of dispersed test scripts into the - tests subdirectory. I think I now have all the file where I - want them, so there shouldn't be anymore upheaval =)O| - Honest! - * tests/Makefile.am: Updated to run the new tests added below. - * tests/other-tests/capitalize.test, tests/other-tests/comments.test, - tests/other-tests/ddivert.test, tests/other-tests/debug.test, - tests/other-tests/esyscmd.test, tests/other-tests/exp.test, - tests/other-tests/foreach.test, tests/other-tests/forloop.test, - tests/other-tests/frozen.m4, tests/other-tests/fstab.test, - tests/other-tests/hanoi.test, tests/other-tests/include.test, - tests/other-tests/indir.test, tests/other-tests/misc.test, - tests/other-tests/modfreeze.test, tests/other-tests/modpath1.test, - tests/other-tests/modpath2.test, tests/other-tests/modpath3.test, - tests/other-tests/modpath4.test, tests/other-tests/modtest.test, - tests/other-tests/multiquotes.test, tests/other-tests/patsubst.test, - tests/other-tests/pushpop.test, tests/other-tests/regexp.test, - tests/other-tests/reverse.test, tests/other-tests/shadow.test, - tests/other-tests/sysv-args.test, tests/other-tests/trace.test, - tests/other-tests/translit.test, tests/other-tests/undivert.test, - tests/other-tests/unfrozen.m4, tests/other-tests/unload.test, - tests/other-tests/wrap.test: New tests based on the contents - of the tests removed below. - * examples/Makefile.am, modules/Makefile.am: Updated to - reflect removed tests. - * examples/defs,modules/defs: Removed. - * examples/capitalize.test, examples/comments.test, - examples/ddivert.test, examples/debug.test, - examples/esyscmd.test, examples/exp.test, - examples/foreach.test, examples/forloop.test, - examples/fstab.test, examples/hanoi.test, - examples/include.test, examples/indir.test, - examples/misc.test, examples/multiquotes.test, - examples/patsubst.test, examples/pushpop.test, - examples/regexp.test, examples/reverse.test, - examples/sysv-args.test, examples/trace.test, - examples/translit.test, examples/undivert.test, - examples/wrap.test, modules/frozen.m4, modules/modfreeze.test, - modules/modpath1.test, modules/modpath2.test, - modules/modpath3.test, modules/modpath4.test, - modules/modtest.test, modules/shadow.test, - modules/unfrozen.m4, modules/unload.test: Removed. - - Move the implementation of GMP support for the mpeval() builtin - into a loadable module that depends on libgmp. mpeval() and - eval() share a common parser, now in m4/evalparser.c; the code - in m4/numb.c and m4/numb.h is now physically split between - m4/eval.c (the eval() backend) and modules/mpeval.c (the - mpeval() backend), rather than being differentiated by cpp - macros and multiple inclusion. The mpeval module is always - built but will generate an diagnostic if it is used from an - installation that didn't link in the gmp library. - * modules/Makefile.am: build and install the new mpeval module. - * modules/mpeval.c: Now contains the former parts of m4/numb.c - and m4/numb.h that are required for gmp support in mpeval(). - * m4/Makefile.am (libm4_la_SOURCES): Removed evalmp.c. - * m4/evalmp.c: Removed. - * m4/m4module.h: Removed conditional prototype for - m4_mp_evaluate(). - * m4/eval.c: Rewritten. Contains the former parts of m4/numb.c - and m4/numb.h that do not rely on gmp. - * m4/evalparse.c: New file, contains the shared parts of the - eval() and evalmp() parser implementations, and is no longer - unencumbered by cpp magic to uncover the right parts. - * m4/numb.h: Removed. It's former contents are split between - m4/eval.c and modules/mpeval.c. - * m4/numb.c: ditto. - - * tests/other-tests/changeword.test: New test. Rudimentary - testing of changeword builtin runs only if --wnable-changeword - was used at configure time. - * tests/mkconfig.sh: Solaris sed (at least) does not parse nested - alternation correctly. Split into two expressions to compensate. - * m4/input.c (m4_input_init): Use m4_ prefix on m4_set_word_regexp. - * modules/Makefile.am: Build changeword module. - * modules/changeword.c (m4_macro_table): Define __m4_changeword__ - only when --enable-changeword was passed to configure. - (builtin_changeword): If --enable-changeword was not used, then - report that changeword() builtin has no support in m4 binary. - -2000-11-28 Gary V. Vaughan - - * src/main.c (main): Fixed a particularly nasty bug is - user_search_path setting -- the -M flag processing must be - extremely careful with search path ordering, or else the default - installed module directory (possibly containing modules from a - previous release) is placed earlier in the search path than any -M - arguments (which are relied upon to load uninstalled modules with - most of the tests in the regresion suite). - - * modules/load.c (builtin_load): Nasty hack to prevent adding - symbols to symtab again if a module is loaded more than once. - * modules/m4.c (builtin_ifelse): removed unused variable argv0. - - * m4/symtab.c (m4_remove_table_reference_symbols): Fixed a - possible NULL pointer dereference. - - * m4/module.c (m4_module_find_by_modname): Renamed from - m4_module_modname_find. Fixed all references. - (m4_module_find_by_builtin): New function. - - * modules/modfreeze.test: load the `load' module with each - invocation. - * src/freeze.c (produce_frozen_state): Simplified in light of - module field in m4_symbol. Allow a third argument for text macros - to name the originating module. - (reload_frozen_state): ditto. - * m4/m4module.h: Fixup prototypes. - * m4/builtin.h (m4_builtin_define): Add a module argument so - that symbols can be registered against the defining module. - (m4_macro_define): ditto. - * m4/m4private.h (m4_symbol): Make the module field const to save - on casting in the rest of the code. - (SYMBOL_MODULE): New macro. - - * m4/symtab.c (m4_remove_table_reference_symbols): Fixed stupid - symbol reference maintenance bugs when removing a symbol from the - symtab. - - * src/stackovf.c (setup_stackovf_trap): Fixed some memory leaks. - -2000-11-27 Gary V. Vaughan - - * configure.in (m4_cv_func_obstack): A better check for whether - libc has an obstack implementation. - * m4/Makefile.am (EXTRA_libm4_la_SOURCES): add gnu-obstack.h. - - * configure.in (--with-modules): Changed semantics. This - option is now used to list modules to be preopened. - * src/m4.h: #include "ltdl.h" unconditionally. - * src/main.c: Removed all dependencies on WITH_MODULES. - * src/freeze.c: ditto. - * modules/Makefile.am: ditto. - * m4/m4.c (builtin_m4exit): ditto. - * modules/modpath1.test: ditto. - * modules/modpath2.test: ditto. - * modules/modpath3.test: ditto. - * modules/modpath4.test: ditto. - * modules/modtest.test: ditto. - * modules/shadow.test: ditto. - * modules/unload.test: ditto. - - * m4/Makefile.am (libm4_la_SOURCES): Removed obstack.c, since it - comes up on demand in LTLIBOBJS now. - * configure.in (getopt_long): Creating and relying on a link for - getopt.h on hosts with no getopt_long() of thier own works - correctly now. This is necessary so that callers of getopt_long() - can simply `#include ': the naive way of doing this - would end up using our own getopt.h and the installed - getopt_long(), which is asking for trouble! - (obstack_init): A similar argument applies to obstack.h and - obstack_init(). - - * m4/ltdl.c: Upgraded to latest bleeding edge version again. - On Solaris-2.5 (at least) the native dlopen implementation - gets confused about m4.o when looking for module "m4". This - version always looks for .la an .$lib_ext suffixed names first - to work around the problem. Sigh. - - * po/POTFILES.in: Take account of these file movements. - * src/Makefile.am (m4_SOURCES): removed eval.c. - (EXTRA_m4_SOURCES): removed numb.c and numb.h. - * m4/Makefile.am (libm4_la_SOURCES): added eval.c. - (EXTRA_libm4_la_SOURCES): added numb.c and numb.h. - * modules/m4.c (builtin_eval): Use m4_evaluate(). - * m4/eval.c: Moved here from src/eval.c to facilitate - implementation of eval() builtin as part of the `m4' loadable - module. - (m4_evaluate): renamed from evaluate for namespace cleanliness. - * m4/numb.c: Moved here from src/numb.c, since it is #included - into eval.c at compile time. - * m4/m4module.h (m4_evaluate): Added prototype. - * src/m4.h (evaluate): Removed prototype. - -2000-11-25 Gary V. Vaughan - - * modules/perl.c (builtin_perleval): Use PL_na for - compatibility with perl-5.6. - - * src/main.c (main): It is now safe to - ``m4_module_install("m4")'', without tripping over the m4 - binary itself! - * m4/ltdl.h, m4/ltdl.c: Upgraded to latest bleeding edge - versions having fixed the insidious module search order bug. - - * m4/Makefile.am (libm4_la_LIBADD): New magic -- we are - supposed to be using @LIBADD_DL@; @DLLDFLAGS@ is dead. - - * configure.in: Figure out whether to use the installed - getopt.h or the supplied one. - * src/Makefile.am: ditto. - - * po/POTFILES.in: List files in their new positions. - - * config/ltmain.sh: This needs to be checked in to match the - libtool macros copied to acinclude.m4 (until a released - libtool copes with m4's needs). - * bootstrap: Run gettextize. - -2000-11-24 Gary V. Vaughan - - * AUTHORS: Added my details. - * TODO: updated. - * NEWS: updated. - * bootstrap: temporary update until released libtool catches up. - - * All files: Use new GNU GPL copyright blurb with current contact - address. - - * configure.in (LTLIBOBJS): Use canonical code for calculation of - this variable. - - * config: renamed acm4 directory to config to be more like - other autoconfiscated packages. - - * configure.in (M4_AC_CHECK_DEBUGGING): Use it. - * config/debug.m4: New file implementing configure macros to add - suitable debug flags to the compiler invocation. - - * modules/load.c: New file implementing the ``load'' and - ``unload'' builtins. - * tests/get-them: Set the module search directory to the modules - build directory in generated tests. - * modules/shadow.test: ditto. - * modules/modtest.test: ditto. - * modules/modpath1.test: ditto. - * modules/modpath2.test: ditto. - * modules/modpath3.test: ditto. - * modules/modpath4.test: ditto. - * modules/modtest.test: ditto. - * modules/modfreeze.test: ditto. - * modules/unload.test: ditto. - - * modules/changeword.c: New file implementing the ``changeword'' - builtin as a loadable module. - * modules/mpeval.c: New file implementing the ``mpeval'' builtin - as a loadable module. - - * src/main.c (main): Load the gnu module if m4 was started - normally -- i.e. without the -G option. - * modules/gnu.c: New file implementing a new loadable module wuth - definitions for all the gnu extension builtins. - * modules/format.c: Moved here from src/format.c. Now included - directly by gnu.c. - - * src/main.c (main): Load the traditional module if m4 was - started in `no_gnu_extensions' mode. - * modules/traditional.c: New file implementing the ``unix'' macro, - required when m4 is executed in traditional mode, as a loadable - module. - - * src/main.c: Renamed from m4.c to avoid confusion with - modules/m4.c. - (main): Always load the m4 module. - * modules/m4.c: New file implementing a new loadable module with - definitions for all m4 builtins that are not gnu extensions. - - * m4/Makefile.am: Adjusted to take new files below into account. - * m4/m4module.h: Prototypes for exported functions and types moved - to this directory from the src directory. - * m4/m4private.h: Moved here from src/m4private.h to facilitate - the migration of all builtin implementations to loadable modules. - * m4/macro.c: Moved this file here from the src directory, - renaming all exported symbols to use the prefix ``m4_''. - * m4/builtin.c: ditto. - * m4/module.c: ditto. - * m4/symtab.c: ditto. - * m4/debug.c: ditto. - * m4/input.c: ditto. - * m4/output.c: ditto. - * m4/path.c: ditto. - * m4/ltdl.h, m4/ltdl.c: ditto. - * m4/utility.c: Odd functions moved here from files in the src - directory to facilitate builtin migration. - -2000-08-12 Gary V. Vaughan - - * src/builtin.c (dump_symbols): Use "Undefined name `%s'" for - error message, to make translators' jobs a little easier. - (builtin_builtin): ditto. - (builtin_traceon): ditto. - (builtin_traceoff): ditto. - Reported by Akim Demaille - - * m4/Makefile.am (pkgincdir): Deleted. Use automake's built in - pkgincludedir instead. - - * m4/m4module.h (rquote): Renamed with a prefix of `m4_' since - it is exported globally. Fixed all references. - (lquote): ditto. - (bcomm): ditto. - (ecomm): ditto. - (DEF_RQUOTE): Renamed with a prefix of `M4_' since it is exported - globally. Fixed all references. - (DEF_LQUOTE): ditto. - (DEF_BCOMM): ditto. - (DEF_ECOMM): ditto. - -2000-07-28 Gary V. Vaughan - - * NEWS: updated. - * TODO: updated. - - * configure.in (AC_CHECK_FUNCS): added bzero and calloc. - (AC_OUTPUT): touch stamp-h.in, not stamp-h. - - * doc/m4.texinfo: Fixed to work with --html option of makeinfo. - Removed `Prev', `Next' and `Up' fields of all @nodes now that - makeinfo calculates them for us, and to make any future - reorganisation easier. - (Frozen files): Document format version 2. - `V' now takes argument `2'. - `F' can take a single argument if symbol and builtin names - are the same, or 3 arguments if the builtin is from a module. - New `S' specification for saving syntax table contents. - New `M' specification for saving loaded module names. - * src/freeze.c: Implement them. - * src/input.c (syntax_code): For interpreting frozen syntax - state. - - * examples/Makefile.am: Add the contents of the WWW directory to - the distribution. - * examples/WWW/Makefile: ditto, - (%.htm): Compares file contents (not just sizes) to determine - whether a change has occured. - * examples/WWW/_header.htm: Bumped version number. - * examples/WWW: Regenerated content. - - * m4/Makefile.am (AUTOMAKE_OPTIONS): Support for non-ANSI - compilers comes much easier without ansi2knr. - * src/Makefile.am (AUTOMAKE_OPTIONS): ditto. - - * m4/list.c: New generic list container type. - * m4/list.h: Interface to new container type. - * m4/Makefile.am (pkginc_HEADERS): Install list.h. - (libm4_la_SOURCES): compile and link list.c. - * src/builtin.c (builtin_tables): Use list container. - * src/module.c (symtab): ditto. - * src/symtab.c (symtab): ditto. - - * m4/system.h: New file for common preprocessor definitions. - * m4/Makefile.am (pkginc_HEADERS): install system.h. - * m4/error.c: Use system.h in place of inline preprocessor. - * m4/error.h: ditto. - * m4/module.c: ditto. - * m4/module.h: ditto. - * m4/xmalloc.c: ditto. - - * m4/error.h (error_one_per_line): Make M4_GLOBAL_DATA for WIN32 - compatibility. - * m4/xmalloc.c (xmalloc_exit_failure): ditto. - - * m4module.h (syntax_table): Renamed with a prefix of `m4_' since - it is exported globally. Fixed all references. - (builtin): ditto. - (module_init_t): ditto. - (module_finish_t): ditto. - (token_data): ditto. - (SYNTAX_OTHER): Renamed with a prefix of `M4_' since - it is exported globally. Fixed all references. - (SYNTAX_IGNORE): ditto. - (SYNTAX_SPACE): ditto. - (SYNTAX_OPEN): ditto. - (SYNTAX_CLOSE): ditto. - (SYNTAX_COMMA): ditto. - (SYNTAX_DOLLAR): ditto. - (SYNTAX_ACTIVE): ditto. - (SYNTAX_ESCAPE): ditto. - (SYNTAX_ALPHA): ditto. - (SYNTAX_NUM): ditto. - (SYNTAX_ALNUM): ditto. - (SYNTAX_LQUOTE): ditto. - (SYNTAX_RQUOTE): ditto. - (SYNTAX_BCOMM): ditto. - (SYNTAX_ECOMM): ditto. - (SYNTAX_VALUE): ditto. - (SYNTAX_MASKS): ditto. - (IS_OTHER): ditto. - (IS_IGNORE): ditto. - (IS_SPACE): ditto. - (IS_OPEN): ditto. - (IS_CLOSE): ditto. - (IS_COMMA): ditto. - (IS_DOLLAR): ditto. - (IS_ACTIVE): ditto. - (IS_ESCAPE): ditto. - (IS_ALPHA): ditto. - (IS_NUM): ditto. - (IS_ALNUM): ditto. - (IS_LQUOTE): ditto. - (IS_RQUOTE): ditto. - (IS_BCOMM): ditto. - (IS_ECOMM): ditto. - (TOKEN_EOF): ditto. - (TOKEN_NONE): ditto. - (TOKEN_STRING): ditto. - (TOKEN_SPACE): ditto. - (TOKEN_WORD): ditto. - (TOKEN_SIMPLE): ditto. - (TOKEN_MACDEF): ditto. - - * m4/m4module.h (voidstar): Removed in favour of `VOID' for - consistency. Fixed all references. - (STRING): Renamed to `m4_string' for consistency, and because if - is exported globally. Fixed all references. - (token_type): Renamed to `m4_token_t' for the same reasons. - (token_data_type): Renamed to `m4_token_data_t' for the same - reasons. - - * m4/m4module.h (XCALLOC): Wrapper macro which handles type - sizes. - (XMALLOC): ditto. - (XREALLOC): ditto. - (XFREE): Wrapper macro which avoids freeing NULL pointers. - - * m4/m4module.h (m4_macro): New type for module defined user - macros. - * modules/modtest.c (m4_macro_table): Define module user macros. - * modules/shadow.c (m4_macro_table): ditto. - - * m4/m4module.h (M4BUILTIN_HANDLER): For defining handlers - declared with M4BUILTIN. - - * m4/xmalloc.c: Use memset if bzero is not available when - emulating calloc with malloc. - (xcalloc): Fallback to malloc/bzero if calloc is not available. - (xfree): Added for consistency. Will not try to free NULL - pointers. - * src/m4.c (xfree): Deleted in favour of the above. - * m4/xmalloc.c (WITH_DMALLOC): preprocess away the entire file if - linking with libdmalloc. - * m4/xstrdup.c (WITH_DMALLOC): ditto. - - * modules/frozen.m4: New test case. - * modules/unfrozen.m4: ditto. - * modules/modfreeze.test: New test. - * modules/unload.test: ditto. - * modules/Makefile.am (EXTRA_DIST): Distribute them. - (TESTS): Use them. - * modules/modpath1.test: Don't try this test if module support is - not compiled in. - * modules/modpath2.test: ditto. - * modules/modpath3.test: ditto. - * modules/modpath4.test: ditto. - * modules/modtest.test: ditto. - * modules/shadow.test: ditto. - - * modules/perl.c: New module. - * modules/perl.m4: Example of using it. - * modules/Makefile.am (perl_la_SOURCES): Build new perl module. - - * src/m4.c (main): Assume interactive mode if STDIN is connected - to a tty. - Changed startup sequence slightly so that syntax is not - initialised from here when loading a frozen file. - - * src/builtin.c: Much improved macro definition style. - * src/m4private.h: Internal structures for m4_builtin and - m4_macro instances. These are not exposed to module writers. - * src/module.c (module_modname_find): Find a module structure - from the its name. - (make_macro_table): Build an internal macro table from a external - definition. - (make_builtin_table): Build an internal builtin table from an - external definition. - - * src/module.c (module_unload): Be extremely careful to remove - builtins and macros that match the module being unloaded -- no - longer assume that the top element can be removed incase another - odule defines an identical name. - * src/symtab.c (remove_table_reference_symbols): remove all symbol - table entries which refer to a given builtin table. - * src/builtin.c (remove_tables): Use it! - -2000-07-13 Thomas Tanner - - * Makefile.am (SUBDIRS): we need modules/ for "make dist" - * acm4/modules.m4: deleted - * bootstrap: don't libtoolize libltdl! - * configure.in: AC_SUBST INCLTDL and LIBLTDL, -with-modules flag: - if set, enable WITH_MODULES and add modules to DLPREOPEN - * examples/misc.test: redirect standard output - * lib/Makefile.am: don't use DLLDFLAGS - * lib/m4module.c: include necessary headers to silence GCC -Wall - * lib/m4regex.c: fixes to silence GCC -Wall - * modules/Makefile.am: don't use DLLDFLAGS, add INCLTDL to INCLUDES, - build modules conditionally - * modules/shadow.c: define symbol aliases before using them - * modules/test.c: define symbol aliases before using them - * po/de.po: update translation - * src/Makefile.am: delete pathconf.h, set MODULE_PATH to - pkglibexecdir, don't use DLLDFLAGS, add INCLTDL to INCLUDES and - LIBLTDL to LIBS. - * src/m4.c: initialize libltdl's preloaded symbols via - LTDL_SET_PRELOADED_SYMBOLS - * src/module.c: libltdl's memory management must be initialized - before calling lt_dlinit!, fix warnings - -2000-01-18 Gary V. Vaughan - - * README: Caveat about nls not supported by dll architecture on - Windows. - - * TODO (MODULE SPECIFIC ISSUES): more ideas for the future. - - * tests/Makefile.am (stamp-TESTS): now works with VPATH. - * src/Makefile.am (m4_LDADD): use $(builddir) for VPATH. - * modules/Makefile.am (LIBS): ditto. - (INCLUDES): search $(top_srcdir) (for eg. ) and then - $(top_srcdir)/m4 (for only ). - * modules/shadow.test: fixed for VPATH. - * modules/modtest.test: ditto. - * modules/modpath4.test: ditto. - * modules/modpath3.test: ditto. - * modules/modpath2.test: ditto. - * modules/modpath1.test: ditto. - - * modules/time.test: Removed due to timezone dependence, - * modules/Makefile.am (TESTS): Removed time.test. - - * configure.in: Use $3 of AC_DEFINE so that we can,,, - * acconfig.h: Remove everything except the gettext parameters. - * acm4/gmp.m4: Add a serial number, and take advantage of $3 of - AC_DEFINE. - * acm4/ltdl.m4: Updated to latest from libtool cvs. - * acm4/modules.m4: Remove code which duplicates ltdl.m4 and - increment serial number. - - * Makefile.am (SUBDIRS): Moved @MODULES_DIR@ to compile before - src dir and immediately after libm4 is built for confidence that - it doesn't rely on the src directory. - (SUBDIRS): Moved doc dir to the end since helptoman.pl and - makeinfo stop the build on cygwin (because they don't work). - - * src/m4.h: use GNU standard #if HAVE_CONFIG_H ideom. - - * m4/m4private.h: ...is not a public header, so moved to src. - Add `#include ', `#define _COMPILING_M4' and - `#include "m4.h". - * m4/Makefile.am (noinst_HEADERS): remove m4private.h. - * src/Makefile.am (noinst_HEADERS): add m4private.h. - * src/builtin.c: `#include "m4private.h"' now takes care of the - above. Duplicates removed. - * src/debug.c: ditto. - * src/eval.c: ditto. - * src/evalmp.c: ditto. - * src/format.c: ditto. - * src/freeze.c: ditto. - * src/input.c: ditto. - * src/m4.c: ditto. - * src/macro.c: ditto. - * src/module.c: ditto. - * src/numb.h: ditto. - * src/output.c: ditto. - * src/path.c: ditto. - * stackovf.c: ditto. - * symtab.c: ditto. - - * po/POTFILES.in: compensate for renaming of lib/*. - * m4/Makefile.am (CLEANFILES): @EXEEXT@ left libtool wrapper behind. - (INCLUDES): Look first in $(top_srcdir) (for eg. ), - and then in $(top_srcdir)/lib (for eg. "m4private.h"). - * src/Makefile.am (m4_LDADD): replace libi/libm4.la with - m4/libm4.la. - * m4/m4error.h: Renamed error.h, for installation to - $prefix/include/m4.. - * m4/m4obstack.h: Renamed obstack.h, for same reason. - * m4/m4regex.h: Renamed regex.h, for same reason. - * m4/m4error.c: Renamed error.c, and use #include "error.h". - * m4/m4obstack.c: Renamed obstack.c, and fix #includes. - * m4/m4regex.c: Renamed regex.c, and fix #includes. - - * lib: moved to m4 to easily support header installation to - $prefix/include/m4. - * Makefile.am (SUBDIRS): renamed lib dir to m4. - * configure.in (AC_OUTPUT): reference m4/Makefile.in. - * acm4/regex.m4: Point to m4/regex.c. - - * examples/foreach.m4: Sanitise quoting. - * examples/foreach.test: New torture test. - From Akim Demaille - -2000-01-17 Gary V. Vaughan - - * src/ltdl.c: Use access() to abort doomed module load attempts - if module file does not exist. - - * src/Makefile.am (m4_SOURCES, EXTRA_SOURCES): getopt.o and - getopt1.o will already be used if appropriate, so I moved getopt.c - and getopt1.c from m4_SOURCES to EXTRA_SOURCES. - - * modules/modpath1.test: Use correct filename in header line. - * modules/modpath2.test: ditto. - * modules/modpath3.test: ditto. - * modules/modpath4.test: ditto. - - Without these changes lt_dlopen("test") attempts to - LoadLibrary("/bin/test") on Windows, which although harmless - generates a spurious error message which spoils most of the tests: - * modules/Makefile.am (EXTRA_DIST): s/test.m4 /modtest.m4 / - (TESTS): s/test.test /modtest.test / - (pkglibexec_LTLIBRARIES): s/test.la /modtest.la / - (test_la_SOURCES, test_la_LDFLAGS): renamed to use modtest. - * modules/modpath1.test: s/test.m4 /modtest.m4 / - * modules/modpath2.test: ditto. - * modules/modpath4.test: ditto. - * modules/modpath3.test: s/-m test /-m modtest / - * modules/shadow.m4: use {un,}loadmodule(`modtest'). - -2000-01-16 Gary V. Vaughan - - * src/ltdl.c (find_file): Updated to new version with fixed memory - allocation bug in `next'. - * src/ltdl.h: updated to match. - - * modules/Makefile.am: Cleaned up and reordered. - -2000-01-16 RenĂ© Seindal - - * modules/Makefile.am (TESTS): New tests for the module system. - - * modules/*.test: New files. - - * src/m4.c (main): Added call to module_init(). - Treats -M and -m as the arguments -D -U and -t, ie deferred. - - * src/m4.h: Added declaration of module_init(). - - * src/module.c (module_init): No longer static - - * modules/Makefile.am ({test,shadow,time,stdlib}_la_LDFLAGS): - Added to shut up automake about non standard libtool library - names. - - * src/module.c: Disabled DEBUG by default. - - * modules/README: Changed example from unload.m4 to shadow.m4 - - * modules/shadow.m4: Renamed from unload.m4 - - * modules/Makefile.am (EXTRA_DIST): Removed unload.m4. - - * src/m4.c (main): Functionality for -m and -M were reversed. - Fixed. - -2000-01-12 Gary V. Vaughan - - * doc/help2man.pl: updated to version 1.020. - - * lib/COPYING.LIB: updated to version 2.1. - - * lib/m4module.h: restructure the M4_SCOPE code to work when - creating a dll which links with libm4.la and both DLL_EXPORT - (for the new dll) and LIBM4_DLL_IMPORT (for m4module.h) are - both defined. - -2000-01-11 Gary V. Vaughan - - Merged the following changes from my tree: - - 1999-06-15 Gary V. Vaughan - - * configure.in (AC_LIBTOOL_WIN32_DLL): Declare that m4 has been - ported to compile shared libs. - - * configure.in (LIBM4_DLL_IMPORT): Discover whether we need to - use `__declspec(dllimport)' when linking libm4.la on win32. - * src/Makefile.am (m4_LDFLAGS): Use dllimport if necessary. - - * configure.in (M4OBJS): Discover whether we need the shipped - implementation of getopt_long. - * src/Makefile.am (m4_LDADD): Link the getopt objects into the - main binary here, as opposed to the module library in lib/libm4.la. - - 1999-06-14 Gary V. Vaughan - - * modules/README: Updated to describe the improved libltdl based - module scheme. - * README (cygwin): Added some compilation notes for building m4 - correctly under cygwin. - * TODO: Cleaned out the entries for the module system since they - are now implemented. - - * *.[ch]: __P is in the compiler's reserved namespace, so replaced - all instances of __P with M4_PARAMS. - - * lib/getdate.h: removed unreferenced file. - - * lib/m4private.h: New file to define the private interface to the - token_data struct, which must be shared between m4module.c, and - builtin.c but not exported to modules built from the installed - m4module.h since it's size changes depending on compile time - options. - - * src/m4.h: Lots of stuff moved to lib/m4module.h. - - * lib/m4module.h: New file to define the interface available when - compiling m4 modules. - * lib/m4module.c: Moved parts of builtin.c, and m4.c which are - necessary for module compilation into this new file. - - * lib/Makefile.am (include_HEADERS): install headers (renamed to - avoid nameclash with other system headers) necessary for compiling - modules. - (libm4_la_SOURCES): always include error.c, obstack.c and regex.c - so that modules can include the (renamed) installed headers and - be guaranteed a matching implementation. - * lib/m4error.h: renamed from error.h. - * lib/m4obstack.h: renamed from obstack.h. - * lib/m4regex.h: renamed from regex.h. - * configure.in (AC_REPLACE_FUNCS): Don't look for a system - implementation, simply include the shipped version - unconditionally, otherwise it is hard for a module to know - whether the m4obstack.h header it is using matches the - implementation it ends up linking against. - (jm_WITH_REGEX): Include regex into libm4 unconditionally for - the same reason. - - 1999-05-18 Gary V. Vaughan - - * examples/misc.test: Don't run this test on machines which don't - have a root user in /etc/passwd (e.g. cygwin). - - * tests/get-them (/^@example$/): Error messages might have a - ``.exe'' suffix to the program name, or else use the libtool - ``.libs/lt-m4'' binary, or generally have an unexpected path. All - of these cases are now catered for when comparing error messages - in generated tests. - * tests/other-tests/*.test: ditto. - * examples/*.test: ditto. - - * tests/defs (M4): use libtool execute mode. - * examples/defs (M4): ditto. - - * tests/get-them (END): explicitly close any open file. - (printthem): In a regular expression, '{' is the start of a repeat - count! Use `[{]' for a literal open brace. - (/^@node /): Don't use substr on a string shorter than the trim - length. - - 1999-05-17 Gary V. Vaughan - - * configure.in (LTLIBOBJS): calculated from LIBOBJS, and - substituted. - (AC_LIBTOOL_DLOPEN): declare that this package will use dlopen. - -2000-01-10 Andreas Schwab - - * tests/other-tests/gmp.test: Find config.sh in build directory. - - * configure.in: Find tests/mkconfig.sh in $srcdir. - - * configure.in: Define HAVE_SIGINFO_T if siginfo_t is defined in - (for SUS2 compliant systems). - - * src/stackovf.c: Check for HAVE_SIGINFO_T in addition to - HAVE_SIGINFO_H. - -2000-01-10 RenĂ© Seindal - - * Prerelease 1.4o. - - * TODO, NEWS: Cleaned up and updated. - - * src/m4.c (main): New variable exit_status for exit status in - case of unreadable files. Now m4 will exit with EXIT_FAILURE if a - file cannot be read instead of EXIT_SUCCESS. - - * src/builtin.c (m4_indir): Changed error message to help - translators (from Akim Demaille ). - - * lib/obstack.[hc], getopt*.[ch]: Updated to newest version from - Cygnus. - - * lib/error.[hc], lib/regex.[hc], lib/strtol.c: Updated to version - from glic 2.1.2. - - * src/input.c (match_input): Reordering of code, to avoid multiple - calls to push_string_init() from obstack_grow(), which can happen - with some compilers (found and fixed by James Bonfield - ). - - * src/stackovf.c: Added prototypes for ultrix. - (setup_stackovf_trap): Added __P to cast. - (Both reported by John David Anglin ) - -2000-01-09 RenĂ© Seindal - - * doc/m4.texinfo (Changequote): Added comment about changing - quotes when the old quote is a part of the new. - - * src/builtin.c (expand_ranges): Added break after trailing dash. - This caused misbehavious on some systems (found and fixed by Akim - Demaille ). - - * AUTHORS: Thomas Tanner included - - * acconfig.h: Added entry for ss_sp (see below). - - * configure.in (use_stackovf): Added check for stack_t with member - ss_base instead of ss_sp (BSDI notably). (Reported by Paul Eggert - ). - - * doc/m4.texinfo (Frozen files): Added a simpler example for - generating frozen files from several input files. - -1999-11-14 Paul Eggert - - * po/POTFILES.in: Add lib/getopt.c, lib/obstack.c, - lib/regex.c, lib/xmalloc.c. - -1999-11-10 RenĂ© Seindal - - * Makefile.am (ACLOCAL_AMFLAGS): Passes -I acm4 to aclocal. - - * src/module.c: reindented. - (module_load): return if this is a repeated load of same module. - (module_init): slight change of logic to avoid repeated - initialisation debug messages. - - * Makefile.am (DIST_SUBDIRS): Added to ensure modules/ is included - in the distribution. - - * modules/Makefile.am (test_la_LDFLAGS): set to -module to silence - automake warnings about missing lib prefix. - (time_la_LDFLAGS): ditto - (stdlib_la_LDFLAGS): ditto - -1999-11-10 Paul Eggert - - * src/m4.h: Include error.h, since our macros use error. - * src/m4.c: Don't need to include error.h. - -1999-11-09 Paul Eggert - - * src/m4.h (voidstar): Define to void * if __STDC__ is defined - and zero, as Solaris 7 cc does. - (bcopy): Remove macro; no longer needed with new obstack.h. - - * src/output.c (freeze_diversions): Don't assume that a - diversion size can fit in `int'. Check for diversion file - size too large to be printed with `unsigned long'. - - * src/Makefile.am (CFLAGS): Omit -Wall. - - * src/stackovf.c (setup_stackovf_trap): Remove cast to unsigned. - - * src/debug.c (trace_format): - Use ANSI C if (defined __STDC__ && __STDC__) || defined PROTOTYPES. - - * src/freeze.c (produce_frozen_state): - Don't assume string lengths fit in int. - -1999-10-13 RenĂ© Seindal - - * po/cs.po: Czech translation added. - - * po/sv.po: Updated Swedish translation. - - * po/ru.po: Updated Russian translation. - - * po/pl.po: Updated Polish translation. - - * po/el.po: Greek translation added. - -1999-10-13 RenĂ© Seindal - - * configure.in (ALL_LINGUAS): Added Greek translation (el). - (ALL_LINGUAS): Added Czech translation (cs). - -1999-03-30 Gary V. Vaughan - - * src/builtin.c: moved module loading functions into... - * src/module.c: entirely new implementation using libltdl. - * po/POTFILES.in: added src/module.c. - * modules/Makefile.am (LTLIBRARIES): Removed lib prefix as these - are modules, not linktime libraries. - (LDFLAGS): added -no-undefined -module and -avoid-version flags. - * modules/stdlib.c (m4_macro_table): use _LTX collision - avoidance on exported symbols. - * modules/test.c (m4_macro_table, m4_init_module, - m4_finish_module): ditto. - * modules/time.c (m4_macro_table): ditto. - - * modules/time2.m4: new file which requires command line loading - of modules. - * src/m4.c (--load-module): dynamically load named runtime module - into running executable before reading the source. - (--module-directory): prepend a directory to the module search - path. - (module_init()): Do this the first time we load a module instead; - if the module subsystem is broken normal m4 scripts can still run. - * src/m4.h (install_builtin_table): is now exported. - -1999-03-26 Gary V. Vaughan - - * src/module.c: removed. No longer required. - * po/POTFILES.in: removed src/module.c. - - * Makefile.am (MAINTAINERCLEANFILES): Remove all the files that - the bootstrap script can recreate. - * acm4/Makefile.am (MAINTAINERCLEANFILES): ditto. - * doc/Makefile.am (MAINTAINERCLEANFILES): ditto. - * examples/Makefile.am (MAINTAINERCLEANFILES): ditto. - * lib/Makefile.am (MAINTAINERCLEANFILES): ditto. - (AUTOMAKE_OPTIONS): reduced strictness to allow COPYING.LIB. - * modules/Makefile.am (MAINTAINERCLEANFILES): ditto. - * src/Makefile.am (MAINTAINERCLEANFILES): ditto. - * tests/Makefile.am (MAINTAINERCLEANFILES): ditto. - - * acinclude.m4: removed. `aclocal -I acm4' handles this much - better. - * acm4/Makefile.am (ACINCLUDE_M4): ditto. - * acm4/gettext.m4: removed. It causes a multiple definition vs. - the installed gettext.m4 file when running aclocal. - -1999-03-25 Gary V. Vaughan - - * configure.in (AM_INIT_AUTOMAKE): bumped version number to - distinguish this from the last prerelease. - (AC_LIBLTDL_CONVENIENCE): build libltdl as a convenience library - in its own subdirectory. - - * modules/Makefile.am (*_SOURCES): renamed to use libtool's "no - lib prefix on a module" feature. - (LDFLAGS): Added `-module -avoid-version' flags to build - versionless module libraries. - * src/builtin.c (m4_load_module): use libltdl. - (module_unload_all): use libltdl. - * src/m4.c (module_init): initialise module loading on demand for - better diagnostics, and so that m4 will still work even if - the module code is broken. - * src/m4.h (module_init): removed. No longer relevant. - * modules/stdlib.c (m4_macro_table): use stdlib_LTX_ prefix on - exported symbols for compatibility with dlpreopening. - * modules/test.c (m4_macro_table, m4_init_module, - m4_finish_module): ditto. - * modules/time.c (m4_macro_table): ditto. - - * bootstrap: New file. Runs all the autoutils in the right order - after a fresh checkout, or a make maintainer-clean. - -1999-02-18 Akim Demaille - - * src/builtin.c (dump_symbols): New function, factoring common - content of m4_dumpdef and m4_symbols. - (m4_dumpdef): Use it. - (m4_symbols): New function, implementing `symbols'. Use it. - * doc/m4.texinfo: Fixed missing commas after @xref, so that the - file compile with modern makeinfo. - (Symbols): New node, documenting symbols. - (direntry): Modernize. - -1998-12-11 RenĂ© Seindal - - * src/builtin.c (predefined_tab): New predefined macros - __m4_changeword__, __m4_gmp__ and __m4_modules__ for testing for - configure time options. - -1998-12-01 Andreas Schwab - - * src/module.c (module_try_load): Don't try to be clever and - overwrite argument string. Instead allocate all constructed - strings locally, since they can have arbitrary lengths. Make - arguments pointers to const. - (module_search): Simplify due to above change. - -1998-11-29 RenĂ© Seindal - - * Prerelease 1.4n. - - * tests/Makefile.am (OTHER_TESTS, OTHER_FILES): New tests. - - * tests/other-tests/import-environment.{m4,test}: New test. - - * tests/other-tests/discard-comments.{m4,test}: New test. - - * doc/m4.texinfo (Invoking m4): Updated for --discard-comments. - - * src/m4.c (main): New option -c --discard-comments. - New global variable discard_comments. - - * src/m4.h (token_type): New TOKEN_NONE for tokens to be - discarded, ie never returned from next_token(). - Added declaration of discard_comments. - - * src/input.c (next_token): Now loops until token type is not - TOKEN_NONE. Comments are now given this type when comments should - be discarded. - - * doc/m4.texinfo (Invoking m4): Updated for --import-environment - and mpeval. - -1998-11-28 RenĂ© Seindal - - * src/m4.c (main): New option --import-environment (no single - letter option). - - * When configured with --with-gmp both the normal (fast) eval() - and the gmp aware mpeval() are defined. To restore previous - bahaviour use "define(`eval', defn(`mpeval'))". - - * tests/other-tests/gmp.m4: Changed to use mpeval(). - - * src/evalmp.c: New file for compiling eval.c as gmp aware. - Just defines USE_GMP if WITH_GMP is defined and includes eval.c. - - * src/eval.c: Now includes "numb.c" directly. Everything in this - file must by static, except evaluate(), which is changed to - mp_evaluate() if USE_GMP in force. - - * src/numb.c: Changed to be included by eval.c instead of being - compiled separately. Everything is declared static. - - * src/numb.h: Removed declarations of functions, as numb.c is now - included by eval.c. - - * src/builtin.c: Declaration of m4_mpeval() added. - Inserted `mpeval' in builtin table. - (do_eval): New function with common code for m4_eval and m4_mpeval. - (m4_mpeval): New function for gmp version of eval. - - * src/m4.h: Declaration of mp_evaluate(). - - * src/Makefile.am (m4_SOUCES): Includes mpeval.c. - (EXTRA_m4_SOURCES): Now has numb.c and numb.h - - * src/m4.c (main): m4 --version also shows which options were used - for compilation, such as: "GNU m4 1.4n (options: modules gmp)" - -1998-11-27 RenĂ© Seindal - - * Error messages now always print program name before input file - name as specified by GNU coding standards. Reported by Akim - Demaille . - - * doc/m4.texinfo (Include): Change due to changed error message - format. - (Eval): Do. - - * tests/get-them: Minor change to sed script due to changed error - message format. - - * src/m4.c (print_program_name): New func used to print program - name, input file and line number in error (). Used as an - error_print_progname handler. - (reference_error): Removed. - (main): Assigns error_print_progname. - - * src/m4.h (M4ERROR): Removed reference_error (). - -1998-11-25 RenĂ© Seindal - - * Updated to libtool 1.2b. - - * src/builtin.c (install_builtin_table): Added braces to avoid - warning of ambiguous 'else'. - - * src/module.c: Inserted search path code from path.c modified to - use new interface. - (module_init): Configured default path used only if M4MODPATH is - not set. - (module_try_load): Now reads libMODULE.la as generated by libtool - for actual module name. - (module_load): Gives better error messages on failure. - - * src/m4.h: Added declarations of structures and functions for - generic search path handling. - - * src/path.c: Removed all module specific code and introduced new - functions of more generic search path handling. - -1998-11-24 RenĂ© Seindal - - * configure.in: Defines INTLINCL to -I$(top_srcdir)/intl if using - included gettext, as might not be found - otherwise. Reported by Andrew Bettison . - -1998-11-22 RenĂ© Seindal - - * src/output.c (insert_diversion): Fixed bug that might cause m4 - to read from standard output! Triggered by input - 'divert(1)undivert(0)'. Test for divnum>0 changed to divnum>=0, - so now 'undivert(0)' does nothing. - -1998-11-18 RenĂ© Seindal - - * Prerelease 1.4m. - - * src/input.c (set_word_regexp): Fixed a bug, where word_regexp - could be changed when compiling a illegal regexp, causing later - use of the regexp to dump core. - - * src/module.c (module_load): Changed error message to conform to - standards. - - * src/m4.c (usage): Added message about reporting bugs. - - * doc/m4.texinfo (Changeword): Corrected a wrong example. - (Changeword): Added note about the type of regexps used. - - * ltconfig, ltmain.sh: New files from Libtool 1.2. - - * configure.in: Added calls to AM_ENABLE_SHARED, AM_DISABLE_STATIC - and AM_PROG_LIBTOOL. - - * acm4/modules.m4 (AM_WITH_MODULES): Redone completely to work - with libtool. - - * modules/Makefile.am: Changed completely to compile modules using - libtool. The modules are compiled as shared libraries, and are - renamed when installed. - - * src/m4.h, src/module.c, acm4/modules.m4, acconfig.h: Renamed - USE_SHL_LOAD to HAVE_SHL_LOAD - - * src/builtin.c (shipout_string): Now tests for a NULL string. - - * src/module.c: New level of indirection around non-portable - functions to load shared objects. Intended to encapsulate the non - portable parts better and to reduce the number of #ifdefs in the - code. - - * Makefile.am (DIST_SUBDIRS): Instead of EXTRA_DIST for added - directory modules/ to the distribution. - -1998-11-15 RenĂ© Seindal - - * Prerelease 1.4l. - - * modules/stdlib.c: New module `stdlib' defining some standard - functions: getcwd, getlogin, getpid, getppid, getuid, getpwnam, - getpwuid, hostname, rand, srand, getenv, setenv, unsetenv, uname. - - * src/builtin.c (shipout_string): New convenience function for - builtins and modules. - - * src/module.c (module_load): Tentative support for - shl_load/shl_findsym, but I cannot test it. Copied from MetaHTML. - - * Makefile.am (SUBDIRS): Directory modules added if configured. - - * modules/Makefile.am: Now correctly compiles and installs - modules in pkglibexecdir. - - * src/m4.h: WITH_MODULES defined iff HAVE_DLOPEN or USE_SHL_LOAD. - These two are now initialised by autoconf macros. - - * src/path.c (module_env_init): MODULE_PATH is always on the - search path. - - * src/Makefile.am: Now generated pathconf.h which defined the - default MODULE_PATH. - - * configure.in (pkglibexecdir): Added defintion of pkglibexecdir, - where modules are installed. - - * acm4/modules.m4: Enhanced with code from MetaHTML, contributed - by Brian J. Fox . This change allow modules to - build and install automatically, and it is prepared for other - interfacec than dlopen(). - - * src/builtin.c (predefined_tab): Added __m4_version__ for the - current version of GNU m4. It is a GNU extension. - -1998-11-14 RenĂ© Seindal - - * tests/Makefile.am (GENERATED_TESTS): Added new - generated-tests/changesy.8.test - - * doc/m4.texinfo (Changesyntax): Documentation for escape - syntax class. - - * src/macro.c (expand_token): Check for escaped macro call before - symbol table lookup. - - * src/builtin.c (m4_changesyntax): Added `@' flag to define escape - characters - - * src/input.c: New static variable use_macro_escape, which is TRUE - iff some character has code SYNTAX_ESCAPE - (input_init): Added initialisation of use_macro_escape. - (check_use_macro_escape): New function to synchronise - use_macro_escape with the syntax table. - (set_quotes): Added call to check_use_macro_escape() - (set_comment): Do. - (set_syntax): Do. - (next_token): Added new case for IS_ESCAPE. - - * src/m4.h (SYNTAX_ESCAPE): Defined as simple syntax category. - -1998-10-13 RenĂ© Seindal - - * Prerelease 1.4k. - - * tests/Makefile.am (GENERATED_TESTS): Renamed gentest to - generated-tests. - - * tests/Makefile.am (OTHER_TESTS, OTHER_FILES): Added manually - maintained tests in tests/other-tests. These currently tests for - 8-bit transparency, multiple precision arithmetic and sync-line - output. Test for stackoverflow detection does not work. - - * examples/Makefile.am (TESTS): Added tests for all example files. - - * examples/mktests.sh: New file. Help program for creating test - files. - - * tests/mkconfig.sh: New file to generate tests/config.m4 and - tests/config.sh. This is for tests of configure selectable - features. Picks up all set WITH_ and ENABLE_ veriables from - config.h - - * src/path.c (path_search): Added argument 'char **expanded_name' - to return the expanded name. - - * src/m4.h: Added 2nd argument to declaration of path_search(). - - * src/m4.c (main): Added 2nd argument to path_search(). - - * src/freeze.c (reload_frozen_state): Do. - - * src/builtin.c (m4_undivert): Do. - (include): Do. - -1998-10-11 RenĂ© Seindal - - * acm4/Makefile.am (ACINCLUDES_M4): Added gmp.m4 and modules.m4 - - * acm4/modules.m4: New file. Defines AM_WITH_MODULES. - - * acm4/gmp.m4: New file. Defines AM_WITH_GMP. - - * configure.in: Introduced AM_WITH_MODULES and AM_WITH_GMP. - - * AUTHORS, ChangeLog: Changed all dates to ISO 8601. - - * intl/: Updated to GNU gettext 0.10.35. - - * doc/m4.texinfo (Format): Documented that format is blind. - - * src/builtin.c (builtin_tab): Builtin format marked as blind. - -1998-10-07 RenĂ© Seindal - - * Prerelease 1.4j. - - * tests/Makefile.am (GENERATED_TESTS): Changed .m4 extension to - .test, as the files are no longer just m4 input. - - * tests/get-them (FILE): Changed .m4 extension to .test. - - * src/m4.h (token_type): New token type TOKEN_SPACE introduced. - Otherwise quoted strings with leading whitespace first in a macro - argument would be eliminated. - - * src/macro.c (expand_token): Handles new token type TOKEN_SPACE. - (expand_argument): Do. - - * src/input.c (next_token): SPACE and NUM/OTHER characters are only - grouped together iff both quote and comment strings are single - character. Otherwise they might include a comment/quote leader. - (next_token): Returns new token type TOKEN_SPACE. - - * src/builtin.c (push_builtin_table): New function to push a - builtin_table on the stack without installing its contents. - (find_builtin_by_name): Added call to push_builtin_table() if - reading frozen files. Otherwise the builtins named in the frozen - files could not be found. - (install_builtin_table): Changed to use push_builtin_table() - -1998-10-04 RenĂ© Seindal - - * po/pl.po: Polish translation added. - - * po/POTFILES.in: src/module.c added. - -1998-10-04 RenĂ© Seindal - - * Prerelease 1.4i. - - * configure.in (ALL_LINGUAS): Added Polish pl.po - -1998-10-03 RenĂ© Seindal - - * Many files: Incorporated changes to implement dynamic modules. - Detailed comments in src/modules.c and modules/README - - * src/module.c: New file, implements the OS dependant parts of - dynamic module loading. - - * src/Makefile.am (m4_SOURCES): Added module.c - - * src/builtin.h: New file, declares some functions from builtin.c - that are of use for other modules (shipout_int, numeric_arg, - skip_space, bad_argc), and the macros ARG() and DECLARE(). - - * src/builtin.c (install_builtin_table): New function. Each - module brings in a builtin_table, which is pushed on a stack. - (struct builtin_table): New struct for list of builtin_tables. - (m4_loadmodule): New function to implement builtin "loadmodule". - (shipout_int): No longer static, to be used by modules. - (numeric_arg): do. - (skip_space): do. - (bad_argc): do. - (builtin_init): changed to call install_builtin_table() - (find_builtin_by_name): Now searches all builtin_tables - (find_builtin_by_addr): do. - - * src/path.c: Reorganised to allow for two search paths, one for - include files and one for modules. - - * src/m4.h: Added declarations for new functions in module.c and - in path.c. - - * src/m4.c (main): Added call to module_init(). - - * modules: New directory with a few demo modules. - - * Makefile.am (EXTRA_DIST): Added modules/* since modules/ is not - in SUBDIRS. - - * configure.in: Added modules/Makefile to AC_OUTPUT. - - * configure.in: Added code to implement --with-modules. Tests for - and -ldl. - - * acconfig.h: Added WITH_MODULES - -1998-10-02 RenĂ© Seindal - - * examples/Makefile.am (pkgdata_DATA): Removed special target for - check and variables TESTS. These tests are now run from the - tests/ directory. - - * tests/Makefile.am (OTHER_TESTS): Added tests from the example/ - directory. The files stay there but the tests are run from the - tests/ directory. - - * tests/Makefile.am (EXTRA_DIST): Added run-test. - - * tests/run-test: New file. Run a test manually - - * tests/Makefile.am, tests/get_them: Moved automatically generated - tests (from the manual) to sub directory tests/gentest/. The - tests/ directory had gotten a bit messy. - -1998-09-06 Erick Branderhorst - - * examples/{comments,ddivert,debug,iso8859,reverse,sysv-args,\ - wrap}.test: Added a few testcases. - -1998-08-21 Erick Branderhorst - - * Prerelease 1.4h. - - * lib/Makefile.am (noinst_HEADERS): regex.h added - - * configure.in (jm_WITH_REGEX, jm_PREREQ_ERROR): - acm4/{error,regex}.m4 (from fileutils-3.16u.tar.gz). - - * acm4/Makefile.am: created providing rules to create - $(top_srcdir)/acinclude.m4 to be used by aclocal. - - * tests/defs (LANGUAGE, LC_ALL, LANG): force them to be - `C'. Reported by Ulrich Drepper. - - * Makefile.am (SUBDIRS): Removed checks directory - * configure.in (AC_OUTPUT): Removed checks/Makefile - - * doc/m4.texinfo (Patsubst,example): @comment added to preserve - the space when m4.texinfo is edited and whitespace.el is active. - (Defn,example): idem. - -1998-08-20 Erick Branderhorst - - * doc/m4.texinfo (Esyscmd): grep ../Makefile instead of - ../COPYING. ../Makefile is a file which is certainly present when - test is executed in testSubDir. One can't be sure that the COPYING - file is in .. or ../.. in all situations, the ../Makefile is - always there. - - * doc/m4.texinfo (Include): adjusted expected test output - according to new tests, i.e. the input will always come from the - file `in' created by the test. - - * tests/Makefile.am: Added three lines at the top to get - esyscmd.1.test working. - - * tests/get-them: modified to generate clearer tests who will need - less maintenance when new test examples are created in - `doc/m4.texinfo'. All tests are small (nearly stand-alone, they - need the generic file `defs') shell scripts creating `in', `ok', - `out' and when apropriate `okerr' and `err' in the directory - `testSubDir' when executed. The compare of `ok' and `out' - (and of `okerr' and `err') will be the exit status of the test. - `out' must match `ok' (and `okerr' must match `err') for the test - to be succesful. - - * tests/[a-b]\{1,8\}.[0-9]+.test: This namespace is reserved for - the tests generated by tests/get-them getting it input normally - from doc/m4.texinfo. The namespace tests/[a-b]+[0-9]+.test (no `.' - (dot) before the numeric part) is reserved for all other (hand - written) tests. The `+' means one or more times. - -1998-08-12 Erick Branderhorst - - * doc/Makefile.am (EXTRA_DIST): helptoman.pl and $(MANS) to - supported short man page to refer to info documentation - * helptoman.pl: added - * configure.in: AC_PATH_PROG(PERL,perl) - * Makefile.am (SUBDIRS): doc after src - - * libitized with libit 0.5 from - ftp://ftp.iro.umontreal.ca/pub/contrib/pinard/maintenance/libit. - - * configure.in (AC_REPLACE_FUNCS): added xmalloc xstrdup - * lib/Makefile.am (libm4_a_SOURCES): removed automakely supported - replacement functions, (libm4_a_LIBADD): @LIBOBJS@ - * configure.in (AM_WITH_REGEX), acconfig.h (WITH_REGEX): added - lib/rx.{c,h}: added - * configure.in (AC_CHECK_FUNC): getopt_long - - * src/m4.c (usage): Report bugs to m4-bugs@gnu.org. - - * TODO: added entry about dependencies - -1998-08-10 RenĂ© Seindal - - * Prerelease 1.4f - - * doc/m4.texinfo (Changesyntax): Added documentation for the macro - "changesyntax". - - * src/builtin.c (m4_changesyntax): Added builtin macro - "changesyntax" to modify the syntax table. - - * src/input.c, src/m4.h, src/macro.c: Implemented an input syntax - table. All categories are assigned a syntax code and tokens are - read according to this table. - -1998-08-09 RenĂ© Seindal - - * src/numb.{c,h}: New files, implements multiple precision eval - using GNU gmp. Originally submitted by John Gerard Makecki - (johnm@vlibs.com), later modified. Tested with GNU gmp 2.0.2. - - * doc/m4.texinfo (Eval): Added documentation for multiple - precision arithmetic library support. - - * src/m4.{c,h}, src/eval.c, src/builtin.c, configure.in: Changes - to accommodate multiple precision eval. - -1998-08-07 RenĂ© Seindal - - * src/input.c (MATCH, match_input), src/m4.h: changed definition - of comment and quote strings to `unsigned int' to allow eight bit - chars (reported by andrewb@zip.com.au (Andrew Bettison)). - - * src/builtin.c, doc/m4.texinfo: Builtin `syncoutput' added by - patch from Mike Howard - -1998-08-06 RenĂ© Seindal - - * gettext.m4: corrected AM_WITH_NLS to handle use of installed - -lintl. - -1998-08-03 RenĂ© Seindal - - * Prerelease 1.4e - - * src/m4.h: Added ifdef ENABLE_NLS around include of - and _ macro. M4 now builds with --disable-nls. - - * src/m4.c (main): reintroduced textdomain(PACKAGE) to get gettext - to look for right message catalogs. Call indef'ed by ENABLE_NLS. - - * configure.in (ALL_LINGUAS): Added complete list of translations: - de fr it ja nl ru sv. - -1998-05-23 Erick Branderhorst - - * po/nl.po: Dutch translation by Erick Branderhorst. - - * po/fr.po: French translation by Erick Branderhorst, based on the - translations by François Pinard in fr.msg and m4.cod. - -1998-05-22 Erick Branderhorst - - * Prerelease 1.4d. - - * src/m4.c: #include not . - - * src/Makefile.am: CFLAGS = -Wall @CFLAGS@. - - * checks/Makefile.am: explicit list tests in CHECKS. - - * configure.in, {,src,doc,lib,examples,checks}/Makefile.am, - src/{ansi2knr.{1,c}} doc/{m4.texinfo,mdate-sh}, missing, - mkinstalldirs, install-sh: Added automake (1.3) support. - - * lib/{alloca.c,error.{c,h},get{date.h,opt.{c,h},opt1.c}, - obstack.{c,h},regex.{c,h},strtol.c,xmalloc.c,xstrdup.c}: - Used libitize (0.4) to update. - - * configure.in, ABOUT-NLS, intl/*, po/*: Added gettextize - (0.10.25) support. Removed LOCALE, fr.msg, m4.cod and adjusted - README accordingly. - - * src/stackovf.c: #ifdef USE_STACKOVF ... #endif to (de-)activate - stack overflow functionality. - -1994-12-03 François Pinard - - * Prerelease 1.4.1. - - * Makefile.in (realclean-local): Delete stamp-h.in. - - * configure.in, {,src,lib}/Makefile.in, src/m4.h, src/m4.c: - Localize, adapting from how it is done in sharutils. - - * fr.tt: New file, for French. - - * configure.in, {,*/}Makefile.in, acconfig.h, src/m4.c, - src/freeze.c: Rename PRODUCT to PACKAGE. - -1994-11-26 François Pinard - - * configure.in: Check for and . - * src/m4.h, src/builtin.c, src/debug.c, src/eval.c, src/macro.c, - src/stackovf.c: Rename _ to __P. - * src/m4.h: Declare _ as a macro returning its argument, or else, - include and declare _ as gettext. - * src/m4.c: Possibly include and call setlocale. - * src/m4.c, src/builtin.c, src/debug.c, src/eval.c, src/freeze.c, - src/input.c, src/macro.c, src/output.c, src/path.c, - src/stackovf.c, src/symtab.c: Use _ macro over all localizable - strings. - -1994-11-07 François Pinard - - * doc/Makefile.in (stamp-vti): Use new -r option to date. - - * configure.in: Put --with-gmp in place, in prevision for John - Gerard's work. - * acconfig.h: Document WITH_GMP. - -1994-11-05 François Pinard - - * Release 1.4. - - * doc/Makefile.in (realclean): Also remove stamp-vti. - Reported by Eric Backus. - -1994-11-02 François Pinard - - * src/freeze.c (produce_frozen_state): If the frozen file cannot - be opened, return immediately after producing the error message. - Reported by Andreas Schwab. - - * configure.in: Check for const only after having found possible - ANSIfying compiler flags, this is of no use to check it before. - Reported by Alexander Lehmann. - -1994-11-01 François Pinard - - * src/macro.c (collect_arguments): Cast obstack arguments to - (voidstar), so avoiding compiler warnings. - Reported by Joseph E. Sacco. - - * src/freeze.c (produce_frozen_state): Cast printed lengths to - (int) so they correspond to %d format items. - Reported by Joseph E. Sacco. - - * src/m4.c (main): Cast the argument to xfree to (voidstar). - * src/symtab.c (free_symbol): Idem. - Reported by Karl Vogel. - -1994-10-31 François Pinard - - * Makefile.in (DISTFILES): Distribute BACKLOG. - - * configure.in: Define PRODUCT and VERSION. - * acconfig.h: Document PRODUCT and VERSION. - * src/m4.c, src/freeze.c: Use PRODUCT and VERSION instead of the - constant string m4 and variable or parameter named version. - -1994-10-30 François Pinard - - * src/m4.h, src/debug.c: Replace all #ifdef __STDC__ by #if - __STDC__. Alliant FX/2800 Concentrix 2.2 (i860-BSD4.3) compiler - defines __STDC__ to 0, for indicating it is *not* ANSI! - Reported by Kaveh R. Ghazi. - - * configure.in: Added obsolescent tests for AIX and Minix. - - * doc/Makefile.in (mostlyclean): Remove texclean in dependencies, - which texclean does not exist anymore. - Reported by Eric Backus, Jim Meyering, John David Anglin and - Joseph E. Sacco. - -1994-10-29 François Pinard - - * aclocal.m4 (fp_C_PROTOTYPES): Force -D_HPUX_SOURCE with -Aa. - Reported by John David Anglin. - - * src/ansi2knr.c: New version, sent by Peter Deutsch. - * aclocal.m4 (fp_C_PROTOTYPES): Substitute empty or ansi2knr for - ANSI2KNR, depending on the fact the compiler is ANSI or not. - * src/Makefile.in: Use -Ovarargs=convert on ansi2knr calls. - Remove the sed filter after ansi2knr for debug.c. Use $O instead - of $U, put underline in extensions rather than in basenames. Use - implicit rules, now that regularity makes this possible. - Have $(OBJECTS) depend on $(ANSI2KNR), so to trigger compilation - of ansi2knr whenever it is needed. - * configure.in: Adjusted for correct STACKOVF substitution. - * src/debug.c (trace_format): When not __STDC__, use (...) as a - parameter list, so ansi2knr will convert it to (va_alist) va_dcl. - Reported by David MacKenzie. - - * Makefile.in: Remove binprefix. Use transform_name instead. - Reported by David MacKenzie. - - * doc/Makefile.in: Create version.texi, use it, clean it. - Reported by Jim Meyering. - -1994-10-28 François Pinard - - * Makefile.in (all, install, uninstall): Depend on Makefile. - - * Makefile.in: For actions invoking $(MAKE) from within compound - sh statements, exit non-zero if the sub-make fails. Otherwise, - the top-level make may exit successfully when it should fail. - Reported by Jim Kingdon. - - * {,/*}Makefile.in: Use && after all cd, in case they fail. - - * {,*/}Makefile.in: Declare PRODUCT and VERSION macros. - (dist): Use PRODUCT and VERSION instead of tricks on .fname. - * configure.in: Substitute PRODUCT and VERSION. - - * {,*/}Makefile.in (dist): Always try a hard link before a copy. - -1994-10-27 François Pinard - - * Makefile.in (mostlyclean-local): Do not remove *~. - * */Makefile.in (mostlyclean): Idem. - Reported by Robert E. Brown and Richard Stallman. - -1994-10-09 François Pinard - - * src/m4.h: Get rid of CONFIG_BROKETS. - -1994-10-02 François Pinard - - * configure.in: Use AC_ARG_PROGRAM. - * aclocal.m4 (fp_C_PROTOTYPES): Substitute @kr@ by kr or empty. - Reported by David MacKenzie. - -1994-10-01 François Pinard - - * configure.in: Do not add -O to CFLAGS for GNU C, now that - configure does it automatically. - Reported by Jim Meyering. - -1994-09-23 François Pinard - - * src/stackovf.c: Declare the handler_t typedef earlier in the - code, use it for stackovf_handler. - (setup_stackovf_trap): Use RETSIGTYPE instead of void while - casting sigsegv_handler. - Reported by Robert Bernstein. - - * src/m4.c (main): Initialize program_name to argv[0] without - basename'ing it. - Reported by Karl Berry. - -1994-09-18 François Pinard - - * src/Makefile.in (TAGS): Include a ../lib/TAGS reference. - Reported by Karl Berry. - -1994-09-14 François Pinard - - * lib/Makefile.in (mostlyclean): Added. - (TAGS): Make in $(srcdir). - - * configure.in: Use `choke me' in test, like everywhere! - - * {doc,examples,lib,src}/Makefile.in (check): Deleted, as - unreacheable and useless. - - * doc/Makefile.in (texclean): Deleted, merged in mostlyclean. - - * lib/Makefile.in (DISTFILES): Distribute TAGS. - (distclean): Do not remove TAGS. - (realclean): Remove it. - * Makefile.in: Make TAGS in lib also, not just in src. - Reported by Karl Berry. - - * Makefile.in (distclean, realclean): Instead of recursively - calling $(MAKE) for the -local part, allow parallel execution of - -recursive and -local, only delay the removal of config.status, - which is repeated in both goals. - -1994-09-13 François Pinard - - * Release 1.3. - - * Makefile.in: Group all *clean-recursive goals in one, using sed - to remove `-recursive' while calling make recursively. Also, use - a subshell for each recursive $(MAKE). - Reported by Jim Meyering. - - * src/m4.h (memcpy): Define with bcopy for BSD systems. - Reported by Kaveh R. Ghazi. - - * src/Makefile.in (ansi2knr): Use $(LIBS) while linking, for SunOS - 4.1.3 requires -ldl to link even ansik2nr, and we need a way to - specify it. - - * configure.in: Use date instead of touch for stamp-h. - * Makefile.in (stamp-h.in): Idem. - - * Makefile.in (distclean, realclean): Force serial execution of - both goals, in case parallel makes are being used. - Reported by Jim Meyering. - - * src/Makefile.in (DISTFILES): Distribute TAGS. - (distclean): Do not remove TAGS. - (realclean): Remove it. - Reported by Karl Berry. - -1994-09-10 François Pinard - - * configure.in: Use fp_ to match aclocal.m4. Revert _OS_ macros - to old names, for following Autoconf. - -1994-09-08 François Pinard - - * Makefile.in (MDEFINES): Remove INSTALL substitutions, for - ./install.sh will not be correctly referred to in sub-Makefiles. - Reported by John David Anglin. - - * doc/Makefile.in (texclean): Remove *.cps and *.fns too. - Reported by Eric Backus. - - * Makefile.in, checks/Makefile.in, doc/Makefile.in, - examples/Makefile.in, lib/Makefile.in, src/Makefile.in: Limit - config.status into remaking this directory's Makefile only. - * Makefile.in (stamp-h): Do not check nor touch stamp-h. - * configure.in (AC_OUTPUT): Touch stamp-h if CONFIG_HEADERS. - Reported by Jim Meyering. - -1994-09-06 François Pinard - - * configure.in: Correct stack overflow detection logic, taking - care of systems having only incomplete implementations (like for - Pyramid 9820 OSx 5.0d). - Reported by Kaveh R. Ghazi. - - * src/Makefile.in (TAGS): Remote -t from etags call. - -1994-09-02 François Pinard - - * lib/Makefile.in (install): Depend on all. - -1994-08-31 François Pinard - - * examples/Makefile.in (mostlyclean): Do not depend on texclean. - Reported by Jim Meyering and John David Anglin. - - * Makefile.in (distclean-local): Delete config.log. - Reported by Jim Meyering. - - Solidify frozen files with respect to -P: - * src/m4.c: Have -P set prefix_all_buitins variable instead of - calling a function by that name. Declare the variable. - * src/m4.h: Adjust declaration for prefix_all_buitins. - * src/builtin.c (builtin_init): Merge in functionality from - previous prefix_all_buitins function, while making entries in the - symbol table, but not modifying the builtin description itself. - - * src/freeze.c (reload_frozen_state): Add a useless `break;', - because *many* compilers do not accept an empty `default:'. - Reported by Akiko Matsushita, Eric Backus, John David Anglin, - Joseph E. Sacco, Kaveh R. Ghazi, Tom McConnell and Ulrich Drepper. - - * configure.in: Use AC_TYPE_SIGNAL. - * src/stackovf.c (setup_stackovf_trap): Use RETSIGTYPE. - Reported by Robert Bernstein. - - * checks/Makefile.in (check): Modify PATH so check-them will find - m4 in the src directory. - * Makefile.in (check): Don't. - Reported by Akiko Matsushita and Jim Meyering. - - * src/output.c (make_room_for, output_character_helper): New - functions, for implementing a global MAXIMUM_TOTAL_SIZE instead of - a per buffer MAXIMUM_BUFFER_SIZE. - - * src/output.c (output_text): New function, for optimizing the - output of strings of characters. Use it. - -1994-08-30 François Pinard - - * doc, src: New directories reorganizing the distribution. - * doc/Makefile.in, src/Makefile.in, examples/Makefile.in: New - files. - * Makefile.in: Adjusted. - * configure.in: Configure new Makefiles. - - * m4.h: Declare STRING typedef. Use it for comment and quote - strings, adjusting all references. (This is the rudiments of a - beginning for the eventual withdrawal of NUL terminated strings.) - * output.c (shipout_text): Accept a length parameter, and use it. - All callers adjusted. - -1994-08-29 François Pinard - - * m4.h: Include if it exists. - * stackovf.c: Don't. - - Clean up for current_diversion variable: - * output.c: Move current_diversion from builtin.c. - * m4.h: Declare current_diversion so builtin.c can access it. - * output.c (output_init, make_diversion): Initialize or update - current_diversion. - * builtin.c (builtin_init, m4_divert): Leave current_diversion - alone. - - Remove limit on number of diversions: - * output.c: Replace ndiversion by diversions, declare it. - (output_init): Allocate only diversion 0. - (make_diversion): Allocate new diversions as needed. - * m4.h, m4.c: Remove NDIVERSIONS and ndiversion related stuff. - * m4.c: Still accept -N, but do nothing with it. - Reported by David MacKenzie. - - Freeze diversions: - * output.c (freeze_diversions): New function. - * m4.h: Declare freeze_diversions. - * freeze.c: Document frozen file format, revise it, call - freeze_diversions to add diversions to frozen format, and code to - reload them properly. - * m4.c: Do not undivert automatically at end when status being - frozen. Do not call builtin_init when reloading frozen state. - - Speed up diversion processing: - * output.c: Add INITIAL_BUFFER_SIZE, MAXIMUM_BUFFER_SIZE, - COPY_BUFFER_SIZE, in-memory diversion buffers, struct diversion - structure and variables, cached variables out of output_diversion, - reallocate_diversion_for and OUTPUT_CHARACTER. - (shipout_text, make_diversion, insert_diversion): Adapted to new - structures. - (insert_file): Use better buffering. - Reported by David MacKenzie. - -1994-08-28 François Pinard - - * Makefile.in, lib/Makefile.in, checks/Makefile.in: Arrange so - dist works from another build directory. - -1994-08-27 François Pinard - - * symtab.c (hack_all_symbols): Use hash_table_size instead of - constant HASHMAX, for -H option to work better. - - * builtin.c (DECLARE): Simplify by using _ (). - - * freeze.c: New file. - * Makefile.in: Compile it, distribute it. - * m4.c: Recognize, document and process --freeze-state (-F) and - --reload-state (-R) options. Pass a true flag to builtin_init - only if no reloading some state. - * builtin.c (define_builtin): Remove static specifier. - (find_builtin_by_name): Remove static specifier. - (builtin_init): Accept and obey a flag argument. - * m4.h: Add declarations for freeze.c, changes for builtin.c. - -1994-08-24 François Pinard - - * builtin.c (dumpdef_cmp): Rewrite so the cast protect the const - specifier. - - * configure.in: Implement --with-dmalloc. - * acconfig.h: Document WITH_DMALLOC. - * m4.h: Add code for when WITH_DMALLOC. - -1994-08-15 François Pinard - - * m4.c (long_options): Use "error-output", the dash was missing. - Reported by Akiko Matsushita. - -1994-08-12 François Pinard - - * m4.h: Include . - * builtin.c, debug.c, m4.c, output.c, stackovf.c: Don't. - * m4.h: Declare len_lquote and len_rquote as size_t, not int. - int. - * input.c: Declare len_lquote, len_rquote, len_bcomm and len_ecomm - as size_t, not int. - * builtin.c (dump_args): Declare len as size_t, not int. - - * debug.c: Prototype the forward declaration of debug_set_file. - - * builtin.c (m4_undivert): Replace div by file, for avoiding the - shadowing of this variable. - * output.c (insert_diversion): Idem. - - * input.c: Delete def_rquote, def_lquote, def_bcomm and def_ecomm. - (input_init): Duplicate default quote and comment strings. - (set_quotes): Free previous quote strings in all cases. Duplicate - even default quote strings. - (set_comment): Free previous comment strings in all cases. - Duplicate even default comment strings. - - * configure.in: Updated for Autoconf 2.0. - * Makefile.in (distclean-local): Also delete config.cache. - - * m4.c (usage): Reorganize the --help output by topic. Include a - description for debugging flags. - -1994-07-29 François Pinard - - * configure.in: If sigaction is available and SA_ONSTACK defined, - use sigaction. Otherwise, if sigvec is available and SV_ONSTACK - defined, use sigvec. Else don't compile stackovf.c. - * stackovf.c (setup_stackovf_trap): Idem. - Reported by Jim Avera, Karl Berry, Kaveh R. Ghazi, Matthias Rabe - and Simon Leinen. - -1994-07-21 François Pinard - - * m4.c (usage): Replace printf par fputs. - -1994-07-18 François Pinard - - * Release 1.2 - -1994-07-17 François Pinard - - * configure.in: Check for sigaction and sigvec. Add a new delayed - check for RLIMIT_STACK, combine in the checking for getrlimit. - All those things are not universally available. - * stackovf.c: Split setting up the trap handler and catching - signals, for better taking care of various configure outcomes. - * examples/stackovf.sh: Correct a typo. - Reported by Eric Backus, Jim Avera and Jim Meyering. - -1994-07-16 François Pinard - - * ansi2knr.c: New version sent by its author, Peter Deutsch. - -1994-07-15 François Pinard - - * Makefile.in: Modify so parallel make will not try making - lib/libm4.a twice simultaneously. - Reported by Jim Meyering. - -1994-07-14 François Pinard - - * stackovf.c (setup_stackovf_trap): Replace "Don't" by "Do not" in - error message, for when no code possibility exists. Even if this - line is completely #ifdef'ed out, it brings a syntax error. - Reported by Andreas Schwab, Jim Meyering and Joseph E. Sacco. - - * Makefile.in (install): Have install depend on all too, for lib - to be remade as needed. - - * examples/stackovf.sh: Try ksh, bsh and bash for shells - providing ulimit, instead of using only ksh. - Reported by Jim Avera and Joseph E. Sacco. - -1994-07-12 François Pinard - - * Makefile.in (check): Have it depend on all instead of m4. In - this way, a change in lib will be detected and processed. - - * builtin.c (numeric_arg): Use strtol and verify the conversion, - instead of using sscanf which stops as soon as there is a - non-digit in the input. Previously, incr(1xyzzy), eval(1,2xyzzy) - and divert(1xyzzy) were all accepted without any warning or error - messages. - * m4.h: Declare strtol as long if not including stdlib.h. - * configure.in: Check for limits.h, and replace strtol if missing. - * lib/Makefile.in: Substitute LIBOBJS. Distribute strtol.c. - * lib/strtol.c: New file, from elsewhere. - Reported by Andreas Schwab. - -1994-07-07 François Pinard - - * macro.c (expand_macro): Cast value to (boolean) prior to - assigning it to traced. - Reported by Tom McConnell. - - * Makefile.in (m4): Always make all in lib first. - Reported by Jim Meyering. - -1994-07-06 Jim Avera - - * stackovf.c: Isolated OS-dependent sections; Improved portability, - adding support for SunOS/BSD (sigvec, sigstack, and 4-parameter signal - handlers), and a default error message if the fault address is not - available (when neither siginfo.h nor BSD sigcontext are supported). - * configure.in: Changes for stackovf.h: Check for sigcontext, - sigaction, sigstack, and define rlim_t as int if necessary. - * acconfig.h: Added HAVE_SIGCONTEXT and rlim_t. - * examples/stackovf.sh: Run m4 -L99999999 to allow stack overflow. - * ansi2knr.c: Fix for func-ptr args; convert "..." to varargs syntax. - -1994-07-05 François Pinard - - * configure.in: Use AC_SET_MAKE. - * Makefile.in: Use @SET_MAKE@. - Reported by Jim Meyering. - - * checks/check-them: Do not trap on SIGQUIT or SIGALRM. - Reported by Ian Taylor. - -1994-07-02 François Pinard - - * configure.in: Remove dependency of USE_STACKOVF on STDC_HEADERS, - because siginfo.h is unrelated to standard headers, and siginfo.h - is already checked for. - Reported by Joseph E. Sacco. - - * acconfig.h, aclocal.m4, m4.h: Replace HAVE_PROTOTYPES by - PROTOTYPES. - * aclocal.m4, configure.in: Replace AC_HAVE_PROTOTYPES by - AC_PROTOTYPES. - -1994-06-29 François Pinard - - * builtin.c (substitute): Use \& to represent this part of the - string which was matched by the whole regexp, instead of - representing the whole string. Any usage of \0 issues a warning - and acts like \&, it will disappear in some subsequent release. - -1994-06-27 François Pinard - - * m4.c: Complete prototype for forwarded declaration of usage. - - * input.c (init_macro_token): Correct own reference in error - message. Previous name get_macro_func was referred to instead. - (next_char): Correct own reference in error message. Previous - name advance_input was referred to instead. - - * m4.h: Declare eval_t and unsigned_eval_t typedefs to 32 bits. - * eval.c (logical_or_term, logical_and_term, or_term, xor_term, - and_term, not_term, logical_not_term, cmp_term, shift_term, - add_term, mult_term, exp_term, unary_term, simple_term): Add - prototype to forwarded declarations. Declare parameter v1 as - eval_t * instead of int *. Same for local variable v2 in dyadic - functions. Same for result in exp_term. - * builtin.c (m4_eval): Declare value as eval_t instead of int. - (ntoa): Declare value as eval_t instead of int. Declare uvalue as - unsigned_eval_t instead of unsigned int. Change casts accordingly. - (shipout_int): Cast first argument of ntoa to eval_t. - Reported by Thorsten Ohl. - - * macro.c: Complete the prototypes of forwarded expand_macro and - expand_token. - Reported by Thorsten Ohl. - - * m4.h: Define voidstar as void * or char * depending on __STDC__. - The Ultrix 3.1 compiler cannot do much with void pointers. - - * builtin.c (dumpdef_cmp): Replace void * by voidstar. - * m4.c (xfree): Replace void * by voidstar. - Reported by Tom McConnell. - - * ansi2knr.1: New, from elsewhere. - * Makefile.in (DISTFILES): Distribute ansi2knr.1 - - * Makefile.in (stamp-h.in): Avoid running ./config.status if - stamp-h does not exist yet. This avoids running it a second time - just after the initial ./configure. - Reported by David MacKenzie and Tom McConnell. - - * m4.h: Replace the enum debug_info declaration with a series of - #define's. The Ultrix 3.1 compiler would otherwise need casting - (int) to most references, when used in expressions. - Reported by Tom McConnell. - -1994-06-25 François Pinard - - * aclocal.m4: Replace FP_PROTOTYPES by AC_HAVE_PROTOTYPES, - following an idea from Brook G. Milligan. AC_HAVE_PROTOTYPES - calls the compiler. Previously, FP_PROTOTYPES was only calling - the preprocessor; by not being subject to CFLAGS, this was - discouraging those flags asking for ANSI compilation. - * acconfig.h: Document HAVE_PROTOTYPES. - * configure.in: Use AC_HAVE_PROTOTYPES instead of FP_PROTOTYPES. - * m4.h: Define _() according to HAVE_PROTOTYPES, not __STDC__. - Reported by Eric Backus. - - * configure.in: Substitute CFLAGS and LDFLAGS, taking their value - from the environment. Default CFLAGS to -g if not set. - * Makefile.in: Have CFLAGS and LDFLAGS substituted from configure. - * lib/Makefile.in: Have CFLAGS substituted from configure. - Reported by Eric Backus and Tom McConnell. - - * configure.in: m4_undefine changeword before using AC_ENABLE. - - * m4.h: Declare prototypes for error (for ANSI compilers only), - prefix_all_builtins and reference_error. - Reported by Tom McConnell. - - * input.c (set_word_regexp): Do not try to initialize the array - test from a string, this does not work with non-ANSI compilers. - Reported by Eric Backus. - - * Makefile.in (dist): Clean examples/ before saving it. - (distclean-local): Also remove stamp-h. - Reported by Eric Backus. - - * Makefile.in (_stackovf.c): Goal for compiling stacokovf.c with - non ANSI compilers. - Reported by Tom McConnell. - - * checks/Makefile.in (clean): Depends on mostlyclean. - (mostlyclean): New goal. - -1994-06-24 François Pinard - - * Makefile.in (DISTFILES): Distribute install.sh. - * install.sh: New file, copied from elsewhere. - Reported by Assar Westerlund and Kaveh R. Ghazi. - -1994-06-23 François Pinard - - * configure.in: Define ENABLE_CHANGEWORD if --enable-changeword. - * acconfig.h: Explain ENABLE_CHANGEWORD. - - [These modifs all depend upon ENABLE_CHANGEWORD and are adapted - from code provided by Pete Chown] - * m4.h: Add original_text field to u_t variant of union u. - Declare TOKEN_DATA_FUNC macro. - * builtin.c: Declare changeword. - (m4_changeword): New function. - * input.c: Include "regex.h", define variables with word regexps. - (input_init): Initialize the word regexp. - (set_word_regexp): New. - (next_token): Declare local variables, use the previous code if - default_word_regexp is true. Else, match using a new code. Save - the original text. - * macro.c (expand_token): Ship out original text if not a macro - name. - Reported by Krste Asanovic and Pete Chown. - - [These modifs all depend upon ENABLE_CHANGEWORD] - * m4.h: Declare external user_word_regexp. - * m4.c: Declare user_word_regexp, and initialize it from - --word-regexp or -W, or NULL if not specified. - * input.c: Use user_word_regexp if specified, instead of - DEFAULT_WORD_REGEXP. - - * Makefile.in (m4): Revert Jan 3 1994 change. I'm unable to - agree with it. - - * Makefile.in, lib/Makefile.in: Limit suffixes to .c and .o. - * checks/Makefile.in: Empty the suffix list. - Reported by Geoff Russell, Joel Sherrill and Roland McGrath. - - * m4.c: Declare nesting_limit and initialize it to 250. - Implement -LNUMBER or --nesting-limit=NUMBER to change its - value. - * m4.h: Declare nesting_limit as external. - * macro.c (expand_macro): Stop execution whenever nesting limit - is exceeded. - Reported by Bengt Mertensson. - - * eval.c (evaluate): Diagnose excess characters in eval input. - Things like `eval(08)' used to return 0 with no diagnostic. - - * m4.h: Capitalize first letter of all macro arguments in - definitions. - - * m4.c: Declare warning_status, initialize it to 0. Add new - option -E, or --fatal-warnings, which sets warning_status to - EXIT_FAILURE instead. - * m4.h: Declare external warning_status. Define EXIT_SUCCESS and - EXIT_FAILURE if not otherwise done by header files. - * m4.c: Delete declarations for EXIT_SUCCESS and EXIT_FAILURE. - * m4.c, input.c, output.c, symtab.c, builtin.c, macro.c, debug.c, - eval.c: Replace 0 by warning_status and 1 by EXIT_FAILURE in first - argument of all M4ERROR calls. - Reported by Noah Friedman. - - * examples/incl-test.m4: Renamed from incl_test.m4. - * examples/include.m4: Include incl-test.m4 instead of - incl_test.m4. - * examples/multiquotes.m4: Renamed from multi-quotes.m. - -1994-06-22 François Pinard - - * configure.in: Avoid USE_STACKOVF if not found. Note - that Jim developped stackovf.c on a 486 running SVR4.0 (ESIX), and - also tested it on a Sun Sparc workstation running SunOS 4.x. - - * format.c (format): When not HAVE_EFGCVT, m4 was failing the - 49.format check, abusing a `union values' argument with sprintf - without selecting the proper field. Now, save the formatting type - first, delaying the fetch of the corresponding argument. - Reported by Joseph E. Sacco and Tom Quinn. - - * format.c (format): Remove const from char *fmt declaration when - not HAVE_EFGCVT, because a NUL may be forced into it. - - * m4.h: Declare atof() when not STDC_HEADERS. - Reported by Joseph E. Sacco. - - * Regenerate configure using Autoconf 1.11, this corrects a - problem about an incorrect cpp seting on NeXT 3.1. - Reported by Alexander Lehmann. - -1994-06-05 François Pinard - - * m4.h (_): Change argument from `x' to `Args'. - -1994-04-22 François Pinard - - * m4.h: Rename Args() to _(). - * m4.h: Remove extern specifier from all function declarations. - -1994-04-22 Jim Avera - - * stackovf.c: New file implementing stack-overflow detection. - * configure.in: Check for getrlimit, sigaction. If all of - standard headers, getrlimit and sigaction, define USE_STACKOVF and - substitute ${U}stackovf.o for STACKOVF. - * acconfig.h: Declare USE_STACKOVF. - * Makefile.in: Distribute stackovf.c, link with $(STACKOVF). - * m4.h: Declare setup_stackovf_trap(). - * m4.c: Call setup_stackovf_trap(). - * tests/stackovf_test.sh: New file. - -1994-04-13 François Pinard - - * checks/Makefile.in: Rename .all-stamp to stamp-checks. - - * Makefile.in (Makefile, etc.): Adapt for Autoconf 1.8. - -1994-01-30 François Pinard - - * m4.h: Remove definition of volatile, not used anymore. - Reported by Jim Meyering and Joseph E. Sacco. - - * m4.h: Consistently use `do { ... } while (0)' in macros, instead - of `if ... else /* nothing */' for if macros. - Reported by Jim Meyering. - - * builtin.c (m4_regexp): Reorganize the code for avoiding a - warning from gcc about `repl' possibly used before defined. - Reported by Jim Meyering. - - * m4.h: Avoid a pre-ANSI together with . - Reported by Jim Meyering. - -1994-01-25 François Pinard - - * m4.h: Move the conditional definition of volatile after the - inclusion of system files, because they may define it first. - -1994-01-04 François Pinard - - * checks/Makefile.in (CHECKS): Add a useless `*' before `[', to - get around a problem with Alpha make seeing a syntax error, there. - Reported by Vern Paxson. - -1994-01-03 François Pinard - - * Makefile.in: Do not define LDFLAGS, use CFLAGS on link calls. - Reported by Richard Stallman. - -1993-12-25 François Pinard - - * configure.in: Correct test for strerror, AC_FUNC_CHECK was used - instead of AC_HAVE_FUNCS. - Reported by Noah Friedman. - -1993-12-01 François Pinard - - * m4.c: Initialize show_help and show_version to zero. - - * m4.c: Ensure EXIT_SUCCESS and EXIT_FAILURE are defined. - Use them in exit() and usage() calls. - -1993-11-27 François Pinard - - * m4.h: Delete extern sys_nerr, sys_errlist declarations, and - syserr() macro. Delete errref, add reference_error and M4ERROR. - * m4.c: Replace errref, which was returning an input reference - string, with reference_error, which prints it on standard error. - * builtin.c, output.c: Use errno as second parameter to error, - instead of using syserr() with %s. - * *.c: Use M4ERROR instead of error: no more errref() with %s. - Doing so, the program name appears after the input reference - instead of before, which eases M-x next-error processing. - -1993-11-24 François Pinard - - * checks/get-them: Escape braces with backslashes in patterns, - because HPUX-9.01 awk needs this. - Reported by Jim Meyering. - -1993-11-22 François Pinard - - * builtin.c: Declare "FILE *popen ();". - - * m4.h: Remove MESSAGE{,1,2}, WARNING1, FATAL{,1}, INTERNAL_ERROR - macros, replace error_message_prefix() declaration by errref()'s. - Declare xrealloc, for use in errref(). - * m4.c: Delete error_message_prefix() function, add errref(). - * *.c: Use error() systematically in place of all error macros, - now that error() flushes stdout first. Make needed adjustments. - - * m4.h: Remove const in sys_errlist[] declaration, it creates - conflicts on SGI and Alpha. - Reported by Kaveh R. Ghazi. - -1993-11-20 François Pinard - - * m4.c: Include instead of "getopt.h". - - * configure.in: Output to config.h. Use HAVE_FUNCS preferably. - * acconfig.h: New, for documenting HAVE_EFGCVT. - * Makefile.in: Distribute acconfig.h, .stamp-h.in and config.h.in, - use them wherever appropriate. Also use -I. for compilations. - * lib/Makefile.in: Use -I.. for compilations. - * *.c: Include or "config.h". - - * m4.h: Test for HAVE_MEMORY_H instead of NEED_MEMORY_H. - * configure.in: Use AC_HAVE_HEADERS(memory.h), delete AC_MEMORY_H. - -1993-11-17 François Pinard - - * builtin.c (m4_eval): Cast strlen to (int) before comparing. - - * input.c (input_init): Initialize quote and comment strings - explicitely instead of calling set_quotes and set_comment: by - doing so, we ensure we do not free uninitialized variables. - - * checks/check-them: Reverse arguments to both diff, so the - expected is on the left and the obtained on the right. - - * m4.h: Add MESSAGE{,1,2}, WARNING1, FATAL{,1} and INTERNAL_ERROR - macros. Delete declarations for m4error, warning, fatal and - internal_error, add declaration for error_message_prefix. - * m4.c: Delete m4error, warning, fatal and internal_error - routines, add error_message_prefix routine. - * *.c: Replace m4error routine calls with MESSAGE* macro calls, - warning with WARNING*, fatal with FATAL* and internal_error with - INTERNAL_ERROR*. - * Makefile.in (_m4.c): Do not adjust ansi2knr output for va_alist, - this is not needed anymore. - - * m4.h: Declare extern FILE *debug. Add DEBUG_PRINT{1,3} and - DEBUG_MESSAGE{,1,2} macros. Delete declarations for debug_print - and debug_message, add declaration for debug_message_prefix. - * debug.c: Remove static specifier for FILE *debug declaration. - Delete debug_print and debug_message routines, add - debug_message_prefix routine. - * builtin.c, debug.c: Replace debug_print routine calls with - DEBUG_PRINT* macro calls. - * input.c, path.c: Replace debug_message routine calls with - DEBUG_MESSAGE* macro calls. - - * m4.h: Remove inclusion of . - * debug.c: Include or . - (trace_format): Use stdarg instead of varargs if __STDC__. - - * configure.in: Remove checks for vfprintf and _doprnt. These - implementations use varargs tricks which are not portable enough. - * lib/vfprintf.c: Deleted. - * lib/_doprnt.c: Deleted. - * lib/Makefile.in: Adjusted accordingly. Remove LIBOBJS. - Reported by Joel Sherrill. - - * path.c (add_include_directory): Use xstrdup. - - * builtin.c (find_builtin_by_name): Declare static. - - * *.[ch]: Add const to a few "char *" declarations. - - * configure.in: Remove commented tests for fileno() and fstat(). - * debug.c: Remove comments about HAVE_FILENO and HAVE_FSTAT. - - * debug.c (debug_flush_files): New. - * m4.h: Declares it. - * builtin.c (m4_syscmd, m4_esyscmd): Use it. - Reported by Nicolas Pioch. - -1993-11-12 François Pinard - - * Makefile.in (m4.dvi): Use m4.texinfo instead of m4.texi. - Reported by Joel Sherrill. - - * builtin.c (prefix_all_builtins): Instead of the table size, use - the null entry at end for stopping the loop. It was overwritten. - Reported by Andreas Schwab and Jim Meyering. - - * builtin.c (prefix_all_builtins): Cast xmalloc to (char *). - Reported by Kaveh R. Ghazi. - - * macro.c (call_macro): Add * in (*SYMBOL_FUNC (sym)) (...). - Reported by Karl Vogel. - -1993-11-09 François Pinard - - * m4.h: Do not define volatile if already defined. - Reported by RenĂ© Seindal. - - * lib/Makefile.in: Add a forgotten ALLOCA=@ALLOCA@. Grrr! - - Reported by Bernhard Daeubler, Eric Backus, Hal Peterson, Hoang - Uong, Ian Taylor, Kaveh R. Ghazi, Tom McConnell and Walter Wong. - -1993-11-08 François Pinard - - * m4.h: Define strchr and strrchr in terms of index and rindex, - instead of the other way around. - * builtin.c, m4.c, path.c: Use strchr instead of index. - - * input.c (next_char): Remove a "break;" after a "return ...;". - Reported by Tom McConnell. - -1993-11-08 François Pinard - - * Release 1.1 - - * configure.in: Do not copy check files in the build hierarchy. - * checks/check-them: Identify the m4 version being checked. For - finding m4, look in $PATH instead of in the parent directory. - * Makefile.in (check): Prepend `pwd` to $PATH before checking. - * checks/Makefile.in (.all-stamp): Always create check files in - the source hierarchy, not anymore in the build hierarchy. - (check): cd to the source hierarchy before performing checks. - Do not copy nor clean COPYING anymore, take it from `..'. - Reported by Tom McConnell. - - * Makefile.in (Makefile): Use $(SHELL). - (config.status): Use $(SHELL). Use "config.status --recheck" - instead of "configure --no-create", which is obsolete. - Reported by Tom McConnell. - -1993-11-05 François Pinard - - * m4.c (usage): Use "%s" instead of "m4" in format string. - Reported by Jim Meyering. - - * Makefile.in: Distribute mkinstalldirs. - Reported by Pierre Gaumond. - Reported by Jim Meyering. - Reported by Tom McConnell. - Reported by Andreas Gustafsson. - - * checks/check-them: Renamed from checks/check_them. - * checks/get-them: Renamed from checks/get_them. - * checks/.all-stamp: Renamed from checks/.all_stamp. - * checks/Makefile.in: Changed accordingly. - Reported by Jim Meyering. - -1993-11-04 François Pinard - - * lib/Makefile.in (dist): Correct permissions on files. - - * output.c: Declare tmpfile, some systems don't. - -1993-11-03 François Pinard - - * checks/Makefile.in (dist): Correct permissions on files. - - * Makefile.in (dist): Ensure recursive linking for subdirectory - `examples', also set read/write permissions on all its files. - - * mkinstalldirs: New, from elsewhere. - * Makefile.in: Use it. - - * debug.c: Synchronize debug messages and regular output when - the debug file and stdout are redirected to the same file. - * configure.in: Add (commented) checks for fileno and fstat. - Reported by Jim Avera. - - * builtin.c (m4_ifelse): Diagnose excess arguments if 5, 8, 11, - etc., arguments, then ignore the superfluous one. m4 used to - diagnose missing arguments and return the empty string. - Reported by Nick S. Kanakakorn. - -1993-11-02 François Pinard - - * m4.c (main): At end of all input, ensure all undiverted text - goes to the main output stream. - Reported by Andreas Gustafsson. - - * m4.c (main): exit (0), instead of return 0. - - * m4.c: Implement -P and --prefix-builtins. - * builtin.c: Delete const specifier on builtin_tab. - (prefix_all_builtins): New. - Reported by Noah Friedman. - Reported by Scott Bartram. - - * c-boxes.el: New, from elsewhere. - * Makefile.in: Distribute it. - - * m4.h: Do not define bcopy if defines it. - Reported by Stephen Perkins. - - * builtin.c (define_macro): Allow a missing second argument, in - which case it is implied empty. Affects define and pushdef. - Reported by Eric Allman. - -1993-11-01 François Pinard - - * m4.h: Add blind_if_no_args in struct builtin, blind_no_args in - struct symbol adn SYMBOL_BLIND_NO_ARGS macro. - * builtin.c: Initialize all the blindness fields in builtin_tab. - (define_builtin): Copy the blindness of a builtin into its symbol. - * macro.c (expand_token): Avoid processing a blind builtin if the - next character is not an opening parenthesis. - Reported by David MacKenzie. - Reported by Noah Friedman. - - * configure.in: Ensure an exit status of 0 on completion. - Reported by Vivek P. Singhal. - - * eval.c (eval_lex): Admit both lower and upper case letters for - bases greater than 10. Only lower case letters were accepted. - - * eval.c (eval_lex): Recognize 0bDIGITS and 0rRADIX:DIGITS syntax. - Reported by Krste Asanovic. - - * eval.c: Rename NOT to LNOT. Add XOR, NOT, LSHIFT and RSHIFT. - * eval.c (logical_not_term): New name for not_term. - * eval.c (xor_term): New, between or_term and and_term. - * eval.c (not_term): New, between and_term and logical_not_term. - * eval.c (shift_term): New, between cmp_term and add_term. - Reported by Krste Asanovic: ~, ^, <<, >>. - Reported by Ben A. Mesander: ** vs ^. - - * m4.c: Delete xmalloc.c, xrealloc.c, xstrdup.c. - * m4.h: Delete xrealloc.c. - * lib/xmalloc.c: New, from elsewhere. - * lib/xstrdup.c: New, from elsewhere. - * lib/Makefile.in: Distribute and compile them. - - * m4.c: Change progname to program_name. - * builtin.c, eval.c, m4.c, m4.h: Rename error to m4error. - * lib/error.c: New, from elsewhere. - * lib/Makefile.in: Distribute and compile error.c. - * configure.in: Check AC_VPRINTF and for strerror. - * m4.c: Delete cmd_error. Use error instead. - * m4.c: Change label capitalisation to "ERROR", "Warning", etc. - - * m4.h: Delete #define const, let Autoconf takes care of this. - - * m4.c: Remove all code conditionalized by IMPLEMENT_M4OPTS. - Merge parse_args into main. Declare argv to be `char *const *', - then remove superfluous casts. - - * m4.c: Rename --no-gnu-extensions to --traditional. - Reported by Ben A. Mesander. - - * m4.c (usage): Add a status parameter. Supply one in various - calls. Add --help processing. Remove -V for --version. - - * lib/Makefile.in: Put $(CFLAGS) last in .c.o rule. - - * lib/Makefile.in: Have an AR=ar declaration. - Reported by Eric Backus. - Reported by Bjorn R. Bjornsson. - Reported by Tom Tromey. - Reported by Kristine Lund. - Reported by Marion Hakanson. - -1993-10-30 François Pinard - - * Makefile.in (m4.info): Use -I$(srcdir) on $(MAKEINFO). - Reported by Noah Friedman. - -1993-10-25 François Pinard - - * Makefile.in: Remove MDEFINES and cleanup. - -1993-06-09 François Pinard - - * Makefile.in (dist): Replace "echo `pwd`" by a mere "pwd". - Create a gzip file. - -1993-02-06 François Pinard - - * Makefile.in, lib/Makefile.in, check/Makefile.in: In dist goals, - ensure 777 mode for directories, so older tar's will restore file - modes properly. - -1993-01-17 François Pinard - - * Makefile.in, lib/Makefile.in: Put $(CFLAGS) after $(CPPFLAGS), - so the installer can override automatically configured choices. - Reported by Karl Berry. - -1993-01-15 François Pinard - - * lib/vfprintf.c: Stolen from Oleo distribution and adapted. The - previous version was not working properly on m68k-hp-bsd4.3. - Reported by Roland McGrath. - - * lib/_doprnt.c: Stolen from Oleo distribution. - * configure.in: Check for _doprnt.c if vfprintf.c selected. - * lib/Makefile.in: Distribute _doprnt.c. - Do not distribute regex.[ch].old anymore. - -1993-01-01 François Pinard - - * Makefile.in, lib/Makefile.in: Reinstate $(CPPFLAGS), use it. - Richard wants it there. - -1992-12-27 François Pinard - - * Makefile.in: Add DEFS to MDEFINES. - * lib/Makefile.in (.c.o): Remove $(CPPFLAGS). - (libm4.a): Remove the library before creating it. - (distclean): Remove tags and TAGS too. - -1992-12-23 François Pinard - - * Makefile.in (dvi, m4.dvi): New goals. - - * builtin.c, eval.c, format.c, input.c, m4.[ch], m4.texinfo, - macro.c, output.c, path.c, symtab.c: Change Copyright from - 1989-1992 to the explicit enumeration 1989, 1990, 1991, 1992. - - * examples/divert.m4: Deleted, this bug has been corrected. - - * Makefile.in (texclean, mostlyclean): New goals. - - * Makefile.in (clean): Remove clutter from ansi2knr. - Reported by Pierre Gaumond. - -1992-12-20 François Pinard - - * Makefile.in: Remove $(CPPFLAGS) from the .c.o rule. The user - might well use CFLAGS is s/he needs it. - - * Makefile.in: Allow installation of info files from a separate - build directory. - Reported by Jason Merrill. - Reported by David MacKenzie. - Reported by Skip Montanaro. - Reported by Erez Zadok. - Reported by Assar Westerlund. - -1992-12-19 François Pinard - - * Release 1.0.3 - This is still a beta release for the future GNU m4 version 1.1. - - * lib/alloca.c: New, from elsewhere. - * lib/Makefile.in: Distribute it. Define and use $(ALLOCA). - - * m4.h: Do not define index/rindex if already defined. If - FALSE/TRUE are already defined, do not redefine them, but merely - define boolean typedef to int. - - * Makefile.in: Use $(DEFS) while compiling ansi2knr. - * ansi2knr.c: Rewrite #ifdef HAVE_STRING_H || STDC_HEADERS, - because some C compilers do not like connectives with #ifdef. - * m4.h: Define `volatile' only if __GNUC__, instead of once for - __GNUC__ and once for __STDC__. - * lib/regex.h: Leave const alone, AC_CONST will take care of it. - - * checks/Makefile.in: Use .all_stamp instead of $(CHECKS) for - Makefile dependencies. Without it, make keeps destroying and - remaking $(CHECKS) in a loop (why?). Distribute .all_stamp. - - * m4.h, m4.c, builtin.c, output.c: Change all divertion/DIVERTION - to diversion/DIVERSION, this was a spelling error. - - * m4.c: Declare version[], remove #include "version.h". - * version.h: Deleted. - * Makefile.in: Remove references to version.h. - - * output.c (shipout_text): Centralize all `#line NUM ["FILE"]' - production, by using a simpler and more robust algorithm. This - solves the problem of synclines sometimes written in the middle of - an output line. Delete sync_line() and output_lines variable. - * m4.h: Remove sync_line prototype and output_lines declaration. - * input.c (next_char), output.c (shipout_text): Remove references - to output_lines. - * input.c (push_file, pop_file): Merely put the value -1 in - output_current_line instead of calling sync_line, for delaying a - single `#line NUM FILE' before next output line. Do not test - for sync_output, because this is unnecessary clutter. - * output.c (make_divertion, insert_divertion): Idem. - * input.c: Rename must_advance_line to start_of_input_line, for - consistency. - - * debug.c (trace_header): Select a new debug line format, which - better complies with GNU standards for formatting error messages. - With option `-dfl', M-x next-error might be used on the output. - * m4.c (vmesg): Adjust format of error output to GNU standards. - * m4.texinfo: Adjust examples for `make check' to work. - - * m4.h, builtin.c, debug.c, input.c, macro.c, path.c: Use upper - case for enum debug_info constants, which were all lower case. - - * builtin.c (m4_regexp, m4_patsubst): Use re_search instead of - re_search_2. - * lib/regex.[ch]: Use new version from textutils 1.3.6, with some - collected patches. I tried a few times using newer regex.[ch], it - mysteriously stopped aborting with this one. Insecure feeling... - * lib/Makefile.in: Distribute regex.[ch].old, just in case! - -1992-12-18 François Pinard - - * m4.c: Change `--no-warnings' to `--silent'. - Reported by David MacKenzie. - - * m4.c: Put all M4OPTS code upon IMPLEMENT_M4OPTS control, and - leave it off for now. See comment in m4.c for justification. - Reported by David MacKenzie. - - * configure.in: Replace AC_USG by AC_HAVE_HEADERS(string.h). - * m4.h, ansi2knr.c, lib/regex.h: Replace USG by HAVE_STRING_H. - - * Makefile.in: Add a new `info' goal. Use macro MAKEINFO. - - * Makefile.in: Ensure recursive cleaning is done before local - cleaning for all clean goals. - - * builtin.c (ntoa): Ensure the value is always interpreted as a - signed quantity, whatever the radix is. - -1992-11-18 Jim Meyering - - * builtin.c, format.c, input.c: Split long lines. - * m4.c: Use typedef macro_definition instead of struct - macro_definition. - * symtab.c: Use typedef symbol instead of struct symbol. - -1992-11-17 François Pinard - - * *.[ch]: Remove all trailing whitespace, in code and comments. - - * configure.in: Find some awk. - * Makefile.in: Add $(AWK) to MDEFINES. - * checks/Makefile.in: Transmit $(AWK) to get_them. - * checks/get_them: Use $AWK instead of gawk. Add a close in the - awk script when switching files, because without this, mawk runs - out of file descriptors. - -1992-11-16 François Pinard - - * Makefile.in (realclean): Delete m4.info*. - Reported by Jim Meyering. - - * Makefile.in: Adjust and link with checks/Makefile. - * checks/Makefile.in: New. - * configure.in: Output checks/Makefile. - - * checks/get_them: Have the dnl header of each test more - recognizable by next-error, also use a better message. - -1992-11-16 Jim Meyering - - * m4.h [__GNUC__]: Use __volatile__ instead of `volatile.' - And use that only if __GNUC__ since we're using it's GCC-specific - semantics that tell the compiler the associated function doesn't - return. - - * builtin.c (substitute): Don't use character as an array index. - (dumpdef_cmp): Make formal arguments `const void *' to avoid - warnings with gcc -W -Wall on systems with qsort prototype. - (m4_errprint): Cast obstack_finish to `char *' to avoid warnings - from gcc -W -Wall. - - * eval.c (most functions): Add parentheses to assignments used - as truth values go avoid warnings from gcc -Wall. - - * input.c, m4.c, output.c, path.c, symtab.c: Declare static - any functions that don't need external scope. - - * builtin.c, debug.c, format.c, m4.c, m4.h, macro.c, symtab.c - (many functions and arrays): Declare `const'. - -1992-11-15 François Pinard - - * *.[ch]: Rename nil to NULL, using the declaration from , - removing the declaration from m4.h. Also rename false to FALSE - and true to TRUE. - - * lib/Makefile.in (Makefile): New goal. - - * Makefile.in, lib/Makefile.in: Add a .c.o rule, so CFLAGS is not - so heavily loaded. It gets more easily overridable, calling make. - Reported by Jim Meyering. - - * Makefile.in (dist): Get .fname from the current directory name, - instead of from version.h. I need updating many files manually, - when the version changes, version.h is just one of them. - -1992-11-14 François Pinard - - * m4.h: Remove the tag `boolean' on the enum introducing typedef - `boolean'. This tag conflicts with on SVR4. - Reported by Tom McConnell. - -1992-11-13 François Pinard - - * m4.texinfo: Correct the examples for 33.divert, 38.divnum, - 39.cleardiv, which were describing missing or spurious newlines. - Modify examples 52.eval, 53.esyscmd and 54.sysval so the results - do not depend on machine word size, `/bin/false' implementation, - or `wc' output format. `make check' is more dependable, now. - - * checks/check_them: Summarize the failed tests by listing their - name, at end. If none, issue `All checks successful'. Output - `Checking' instead of `Input file:'. - - * checks/get_them, checks/check_them: Reindented. - - * Makefile.in (dist): chmod a+r before making the tar file. - -1992-11-12 François Pinard - - * builtin.c (m4_dnl): Diagnose any parameter to `dnl'. - - * input.c (next_token): Reinitialize token_buttom just after using - it as a watermark with obstack_free. Or else, a future token, big - enough for triggering reallocation of the obstack chunk, could - void the initialized value of token_buttom, later causing panic in - obstack_free. Rename token_buttom to token_bottom everywhere. - - * m4.h: Before declaring errno, first include and - ensure that it does not define errno. - Reported by Richard Stallman. - -1992-11-11 François Pinard - - * builtin.c: Define and use DECLARE macro for builtins. - - * builtin.c (m4_ifelse): Avoid any diagnostic when exactly one - argument, this is a common idiom for introducing long comments. - - * builtin.c (m4_ifelse): If 3n + 2 arguments, diagnose missing - arguments. The last argument was silently ignored. - - * m4.c (cmd_error): Add a missing semicolon before va_end(). - -1992-11-10 François Pinard - - * Makefile.in: Now handle protoized sources. Define and use U. - Compile and use ansi2knr with old compilers. Update DISTFILES. - Add `aclocal.m4' to `configure' dependencies. - * ansi2knr.c: New, from Ghostscript distribution. - * configure.in: Define U through FP_PROTOTYPES for old compilers. - Add AC_ISC_POSIX, AC_CONST, AC_SIZE_T. - * aclocal.m4: New, provide FP_PROTOTYPES. - * m4.h: Conditionnaly protoized through Args, save for varags. - * builtin.c: Protoized. Then: - Include if size_t is not defined, before "regex.h". - (m4_ifelse): Fetch built-in name properly for diagnostic. - (m4_dumpdef): Remove wrong (char *) cast calling dump_symbol. - (m4_regexp): Add const to `msg' declaration. - (m4_patsubst): Add const to `msg' declaration. - * debug.c: Protoized, save for varargs. - * eval.c: Protoized. - * format.c: Protoized. - * input.c: Protoized. - * m4.c: Protoized, save for varargs. Then: - (xfree): Accept void * instead of char *. - (xmalloc): Return void * instead of char *. - (xrealloc): Accept and return void * instead of char *. - * macro.c: Protoized. - * output.c: Protoized. - * path.c: Protoized. Then cast some (char *) over xmalloc's. - * symtab.c: Protoized. - -1992-11-06 François Pinard - - * m4.texinfo: Remove directory from diagnostics in 30.include, - 51.eval, 56.errprint and 57.m4exit tests. - - * m4.h: Remove declarations for int or void system functions, they - cause more conflicting trouble than they make good. - - * configure.in: Avoid configuration header file. Add some tests. - * m4.h: Remove #include "config.h". - * Makefile.in, lib/Makefile.in: Implement Autoconf interface. - Then, rewritten for better compliance with GNU standards. - -1992-11-05 François Pinard - - * format.c (format): Avoid syntax error if not HAVE_EFGCVT, - because of a misplaced #endif. - - * Many *.[hc] files: Correct intra-line spacing here and there, - according to GNU indent 1.6 advice. - - * configure.in: New, using Autoconf 1.2. - * m4.h: Reverse NO_MEMORY_H to NEED_MEMORY_H. - * Delete old configure.in, configure, etc/configure.in, - etc/configure, lib/configure.in, lib/configure and config/*. - Reported by Jason Merrill. - - * symtab.c (hash): Change (char) NULL to '\0'. - Reported by Jason Merrill. - - * Delete .vers, etc/newdist.sh, etc/newvers.sh and - etc/nextvers.sh. Release numbers will be edited `by hand'. - * version.h: De-automatize, force value in. - - * m4.c: Changes in order to use a newer getopt.h. - Reported by David MacKenzie. - - * checks/: New name for examples/. - * checks/get_them: New location for etc/get_examples. - * checks/check_them: New location for etc/check_examples. - * Makefile.in, checks/get_them, checks/check_them: Adjust. - * lib/vfprintf.c: New location for etc/vfprintf.c. - * Delete empty etc/. - * examples/: New name for test/. - -1992-03-10 François Pinard - - * Makefile.in (check): Add m4 as dependency. - - * m4.c: Accept --no-warnings instead of --no_warnings, and - --no-gnu-extensions instead of --no_gnu_extensions. Make the - usage message more informative. - Reported by David MacKenzie. - -1992-03-09 François Pinard - - * etc/check_examples: New name for check_examples.sh. - * etc/get_examples: New name for get_examples.sh. - * Makefile.in, etc/Makefile.in: Use new names. - - * Makefile.in: Transmit $(CC) while making in lib. - - * Many *.[hc] files: GNU indent'ed, with further fine tuning of - code disposition by hand. - -1992-03-08 François Pinard - - * m4.h: Delete definitions for abort() and exit(). - Reported by Richard Stallman. - - * config/hmake-unicos, config/s-unicos.h: New files. - Reported by Hal Peterson. - - * eval.c (exp_term): Have N^0 return 1. - Reported by Michael Fetterman. - - * eval.c, input.c, m4.h: Remove last comma in enums. - Reported by Mike Lijewski. - - * Transfer of maintenance duties from RenĂ© to François. - -1991-10-24 RenĂ© Seindal - - * Release 1.0. Many thanks to those, who provided me with bug - reports and feedback. - - * Uses GNU configure, taken from the gdb distribution. - - * Uses GNU getopt(), with long option names. - - * The -Q/+quiet option is added, which suppresses warnings about - missing or superflous arguments to built-in macros. - - * Added default options via the M4OPTS environment variable. - - * The built-in format can now be configured to use sprintf as - the formatting engine, for systems without [efg]cvt(3). - - * GNU library code is moved to the ./lib subdirectory; other - utility files are now in ./etc. - - * Several minor bugs have been fixed. - -1991-07-26 RenĂ© Seindal - - * Fixed various bugs. Release 0.99, manual 0.09. Many thanks to - François Pinard and Roland H. Pesch for providing me with reports. - - * The builtins incr and decr are now implemented without use of - eval. - - * The builtin indir is added, to allow for indirect macro calls - (allows use of "illegal" macro names). - - * The debugging and tracing facilities has been enhanced - considerably. See the manual for details. - - * The -tMACRO option is added, marks MACRO for tracing as soon - as it is defined. - - * Builtins are traced after renaming iff they were before. - - * Named files can now be undiverted. - - * The -Nnum option can be used to increase the number of - divertions available. - - * Calling changecom without arguments now disables all comment - handling. - - * The function m4_patsubst() is now consistently declared - static. - - * A bug in dnl is fixed. - - * A bug in the multi-character quoting code is fixed. - - * Several typos in the manual has been corrected. More probably - persist. - - * The m4.info file is now installed along with the program. - -1990-11-15 RenĂ© Seindal - - * Updated and enhanced version. Release 0.75, manual 0.07. - - * Implemented search path for include files (-I option and - M4PATH envronment variable). - - * Implemented builtin "format" for printf-like formatting. - - * Implemented builtin "regexp" for searching for regular - expressions. - - * Implemented builtin "patsubst" for substitution with regular - expressions. - - * Implemented builtin "esyscmd", which expands to a shell - commands output. - - * Implemented "__file__" and "__line__" for use in error - messages. - - * Implemented character ranges in "translit". - - * Implemented control over debugging output. - - * Implemented multi-character quotes. - - * Implemented multi-character comment delimiters. - - * Changed predefined macro "gnu" to "__gnu__". - - * Changed predefined macro "unix" to "__unix__", when the -G - option is not used. With -G, "unix" is still defined. - - * Changed "shift", "$@" and "$*" to not insert spaces afters - commas. - - * Added program name to error messages. - - * Fixed two missing null bytes bugs. - -1990-01-22 RenĂ© Seindal - - * Initial beta release. Release 0.50, manual 0.05. - - - ----- - - Local Variables: - coding: utf-8 - End: - - Copyright (C) 1990-1994, 2000-2001, 2003, 2005-2010, 2013-2014, - 2017 Free Software Foundation, Inc. - - Copying and distribution of this file, with or without - modification, are permitted provided the copyright notice - and this notice are preserved. diff --git a/HACKING b/HACKING deleted file mode 100644 index 0e5cd66b..00000000 --- a/HACKING +++ /dev/null @@ -1,334 +0,0 @@ -GNU M4 -****** - -1. Introduction -=============== - -This file attempts to describe the processes we use to maintain M4, -and is not part of a release distribution. - - -2. Maintenance Notes -==================== - -* If you incorporate a change from somebody on the net: - If it is a large change, you must make sure they have signed the - appropriate paperwork, and be sure to add their name and email - address to THANKS. AUTHORS is built from the FSF list of copyright - assignments, on fencepost.gnu.org. - -* If somebody reports a new bug, write a test case, then mention his - name in the ChangeLog entry. - -* The correct response to most actual bugs is to write a new test case - which demonstrates the bug. Then fix the bug, re-run the test suite, - and check everything in. - -* Changes with user-visible effects must be mentioned in NEWS. - -* New macros must be blind, or else prefixed with `m4' or `__', in - order to minimize backward compatibility issues with previous - releases of M4 when processing English text. - -* GNU Coding Standards should be followed: - http://www.gnu.org/prep/standards/ - Additionally, while GNU M4 is not yet POSIX compliant, we are trying - to get closer to it (although some design decisions state that POSIX - compliance should only happen when POSIXLY_CORRECT is in the - environment or the -G option was passed on the command line): - http://www.opengroup.org/onlinepubs/009695399/utilities/m4.html - -* Except for third-party files (libtool, gnulib, ...), all .c files - should #include before anything else (since there are some - #defines in config.h that potentially impact system headers, such as - when the user does ./configure --disable-assert). This means that no - .h files need to #include . However, users compiling - external modules should be able to compile without , since - is specific to the M4 build and is not installable. - - -3. Bootstrapping -================ - -* The master M4 repository is stored in git. You can obtain a read-only - copy with: - git clone git://git.sv.gnu.org/m4.git - or - cvs -d:pserver:anonymous@pserver.git.sv.gnu.org:/srv/git/m4.git \ - co -d m4 HEAD - - If you are a member of the savannah group for M4, a read-write - copy can be obtained by: - git clone @git.sv.gnu.org:/srv/git/m4.git - -* Before you can build from git, you need to bootstrap. This requires: - - A pre-installed version of GNU M4 1.4.5 or later, built from a - package (recommend 1.4.13 or later) - - A git checkout of Autoconf (2.63b-41 or later) - - Automake 1.10b or later - - Libtool 2.2 or later - - Gettext 0.16 or later - - Gperf 3.0 or later - - Help2man 1.29 or later - - Xz 4.999.8beta or later (from ) - - Texinfo 4.8 or later - - Any prerequisites of the above (such as perl, tex) - - Note that none of these bootstrapping dependencies should be required - by a distributed release. - -* M4 includes gnulib as a git submodule. By default, the bootstrap - script will attempt to run - git submodule update --init - to grab a gnulib clone from the official read-only location of - git://git.sv.gnu.org/gnulib.git - - However, this can be network and disk intensive. If you already have - another gnulib clone on your disk, you can use the environment - variable GNULIB_SRCDIR to point to the previous checkout to speed up - the process. Additionally, both the bootstrap script and gnulib-tool - require a shell that supports functions, so you can set the - environment variable CONFIG_SHELL to choose a better shell on systems - (like Solaris) where /bin/sh is lacking. Thus, you may find it - convenient to run: - GNULIB_SRCDIR=path/to/gnulib CONFIG_SHELL=path/to/sh \ - path/to/sh ./bootstrap - - A read-only copy of gnulib can be obtained by: - git clone git://git.sv.gnu.org/gnulib.git - or - cvs -d:pserver:anonymous@pserver.git.sv.gnu.org:/srv/git/gnulib.git \ - co -d gnulib HEAD - - Using a CVS checkout might work, but it is relatively untested, - particularly now that we use a git submodule for gnulib. - - If you are a member of the savannah group for gnulib, a read-write - copy can be obtained by: - git clone @git.sv.gnu.org:/srv/git/gnulib.git - - If you are behind a firewall that blocks the git protocol, you may - find it useful to do: - git config --global url.http://git.savannah.gnu.org/r/.insteadof \ - git://git.sv.gnu.org/ - to force git to transparently rewrite all savannah git references to - instead use http. - -* Either add the gnulib directory to your PATH, or run - GNULIB_TOOL=path/to/gnulib/gnulib-tool ./bootstrap - -* When it is time for a release, it is a good idea to bootstrap with - official releases of the autotools, rather than git builds, to reduce - the pain of a user re-running bootstrap on the packaged M4. However, - files installed by Automake should be updated to the latest version - from their respective upstream source, rather than the version that - shipped with the automake release. - -* Normally, after running bootstrap, 'git status' should not show any - differences; if things changed, please provide a patch or at least - report it as a bug. One case where things are changed is if the - gnulib submodule comes from an older date than the current installed - libtool, such that libtoolize will replace the symlinks to an older - version of build-aux files with their newer counterpart; the fix to - this is updating the submodule to a newer gnulib version. - -* If you would like to check that you are not missing out on any useful - gnulib modules, comment out the gl_ASSERT_NO_GNULIB_POSIXCHECK in - configure.ac, then run 'make CFLAGS='-DGNULIB_POSIXCHECK=1' with gcc, - and look at the resulting warnings. - - -4. Test Suite -============= - -* Use - make check - liberally, on as many platforms as you can. Use as many compilers and - linkers you can. - -* Some of the testsuite is generated from the documentation. - All instances of @example in doc/m4.texinfo that are not preceeded by - "@comment ignore" are turned into tests in the tests directory. - - -5. Editing 'ChangeLog' -====================== - -* The ChangeLog is generated from git commit comments. Each commit log - should start with a one-line summary, a blank line, and then a - ChangeLog-style entry for all affected files. However, it's fine -- - even recommended -- to write a few lines of prose describing the - change, when the summary and ChangeLog entries don't give enough of - the big picture. Omit the leading TABs that you're used to seeing in - a "real" ChangeLog file, but keep the maximum line length at 72 or - smaller, so that the generated ChangeLog lines, each with its leading - TAB, will not exceed 80 columns. As for the ChangeLog-style content, - please follow these guidelines: - - http://www.gnu.org/software/guile/changelogs/guile-changelogs_3.html - -* When in doubt, check that emacs can syntax-color properly in - change-log-mode. And preferably use emacs 'C-x 4 a' - (add-change-log-entry-other-window) to open ChangeLog with an - appropriate new template, which you can then paste into your git - commit editing session. - -* See the GNU Coding Standards document for more details on ChangeLog - formatting. - -6. Formatting -============= - -* Use space-only indentation in nearly all files (Makefile inputs being - the exception). - - If you use Emacs and your m4 working directory name matches, - this code in your ~/.emacs enables the right mode: - - ;; In m4, indent with spaces everywhere (not TABs). - ;; Exceptions: Makefile and ChangeLog modes. - (add-hook 'find-file-hook '(lambda () - (if (and buffer-file-name - (string-match "/m4\\>" (buffer-file-name)) - (not (string-equal mode-name "Change Log")) - (not (string-equal mode-name "Makefile"))) - (setq indent-tabs-mode nil)))) - -* Since the source code was massively converted from tabs in December - 2009, you may find it helpful to use 'git diff -w' and 'git blame -w' - helpful for overlooking the whitespace changes. - -* Avoid #ifdefs inside function bodies, whenever possible. If you - encounter a portability issue, it is better to propose a gnulib module - that works around it, and have m4 use that module. - - -7. Release Procedure -==================== - -* If you are an m4 maintainer, but have not yet registered your - gpg public key and (preferred) email address with the FSF, send an - email, preferably GPG-signed, to that includes - the following: - - (a) name of package(s) that you are the maintainer for, and your - preferred email address. - - (b) an ASCII armored copy of your GnuPG key, as an attachment. - ("gpg --export -a YOUR_KEY_ID > mykey.asc" should give you - this.) - - When you have received acknowledgement of your message, the proper GPG - keys will be registered on ftp-upload.gnu.org and only then will you be - authorized to upload files to the FSF ftp machines. - -* If you do not have access to the mailing list administrative interface, - approach the list owners for the password. Be sure to check the lists - (esp. bug-m4) for outstanding bug reports also in the list of - pending moderation requests. This step is not strictly necessary, but - helps, since by default, m4-announce rejects all posts, so you have to - get an administrator to allow your announcement through. - -* Make sure you have rsync installed. - -* Make sure you have GNU make installed. - -* Make sure you have an up-to-date version of help2man installed. - -* Make sure your locale is sane, e.g. by exporting LC_ALL=C. - -* Make sure you are happy with the particular gnulib version recorded as - the gnulib submodule. If necessary to update to the latest, run: - git submodule foreach git pull origin master - git commit -m 'Update gnulib submodule to latest.' gnulib - In particular, ensure that the gnulib version is at least as new as - the latest stable libtool release. - -* Update the version number in NEWS, and mention in README whether the - release is stable. See - http://www.gnu.org/software/libtool/contribute.html for details of the - numbering scheme (M4 uses a similar scheme to libtool, although - intra-release versions carry more information thanks to - git-version-gen). - -* Run ./bootstrap, perhaps with environment variables set. - -* Run ./configure (a VPATH build should work, but is less tested). - -* Run `make'. The file doc/m4.1 needs to exist for a distribution, and - be up-to-date with m4 --help output, but `make dist' intentionally - does not depend on running a built binary. - -* Run `git commit' from the source tree if there are any changes from - the previous steps. - -* Run `git tag -s -m -u v' with the desired - version number. Do not push anything upstream at this point. - -* Run `make distcheck'. If there are any problems, fix them, then run - `git tag -d v' and start again from the `git commit' step. - -* Run `make ', with target set to `stable', `alpha', or `beta' - as appropriate. This will run various additional checks. - -* Run './build-aux/gnupload --to [dest].gnu.org:m4 [files]' to create - detached gpg signature and clear signed directive files, and upload - the combination to the correct location. For an alpha release, - gnupload will place files in alpha.gnu.org, in /incoming/alpha; for a - full release, gnupload will place files in ftp.gnu.org, in - /incoming/ftp. Verify that the files uploaded successfully before - sending an announcement. - -* Send announcement to m4-discuss@gnu.org, m4-announce@gnu.org, and - autotools-announce@gnu.org. If not an alpha send to info-gnu@gnu.org - as well. Use gnulib/build-aux/announce-gen to form an initial - template for the announcement (you may also need to install the perl - module Digest::SHA1). Contact a list administrator for m4-announce in - advance to ensure your post will make it through (the list is normally - set to silently discard all posts, even from subscribers). - -* Update version number in configure.ac to next alpha number. - See http://www.gnu.org/software/libtool/contribute.html for details of - the numbering scheme. - -* Update NEWS and README to start the intra-release changes, and run - `git commit'. Then run `git push origin refs/tags/v' to push - the release tag and complete the release. - -* For stable releases, update the webpages. - Run `build-aux/gnu-web-doc-update', which runs `make web-manual' on a - temporary git branch corresponding to the release, then copies the - contents of doc/manual into a CVS checkout of the M4 manual - repository. Follow up with any needed edits to m4.html, using: - export CVS_RSH=ssh - cvs -z3 -d:ext:@cvs.savannah.gnu.org:/web/m4 co m4 - -* Update the Free Software Directory. Browse to: - http://directory.fsf.org/project/m4/ - and send an email to mentioning any content - that needs to be updated. - ------------ -Copyright (C) 2004-2010, 2013-2014, 2017 Free Software Foundation, Inc. - -The canonical source of this file is maintained with the -GNU M4 package. Report bugs to bug-m4@gnu.org. - -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 . - -Local Variables: -mode: text -fill-column: 72 -End: -vim:tw=72 diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index d4326965..00000000 --- a/Makefile.am +++ /dev/null @@ -1,453 +0,0 @@ -## Makefile.am - template for generating Makefile via Automake -## -## Copyright (C) 2000-2001, 2003-2010, 2013-2014, 2017 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 . -## -## Written by Gary V. Vaughan - -config_aux_dir = build-aux -config_macro_dir= $(config_aux_dir)/m4 - -SUBDIRS = po m4/gnu . doc tests/gnu - -ACLOCAL_AMFLAGS = -I build-aux/m4 -AUTOMAKE_OPTIONS = nostdinc - -gitlog_to_changelog = $(srcdir)/$(config_aux_dir)/gitlog-to-changelog -git_log_fix = $(srcdir)/$(config_aux_dir)/git-log-fix -thanks_gen = $(srcdir)/$(config_aux_dir)/thanks-gen - -changelog = $(distdir)/ChangeLog -changelog_old = $(srcdir)/ChangeLog.old -thanks = $(distdir)/THANKS -no_thanks = $(srcdir)/NO-THANKS - -# Prime the variables that will be augmented by libtool. -# FIXME - the -export-symbols-regex ".*" is a hack to work around the -# fact that on cygwin, the convenience library libltdl exports symbols, -# which effectively disables the auto-exporting of all other symbols. -# Revisit this if libtool on cygwin improves. -# See http://lists.gnu.org/archive/html/libtool-patches/2007-02/msg00062.html -AM_CPPFLAGS = -I$(srcdir) -I. -AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS) -AM_LDFLAGS = -no-undefined -export-dynamic -export-symbols-regex ".*" -EXTRA_DIST = -BUILT_SOURCES = -CLEANFILES = -DISTCLEANFILES = -MOSTLYCLEANFILES= -MAINTAINERCLEANFILES = - -include_HEADERS = -noinst_LTLIBRARIES= -lib_LTLIBRARIES = -check_LTLIBRARIES = -EXTRA_LTLIBRARIES= - -# Additional configuration. Version management comes from suggestions -# given in build-aux/git-version-gen. -AM_CPPFLAGS += -Im4/gnu -I$(srcdir)/m4/gnu \ - -Im4 -I$(srcdir)/m4 -AM_LDFLAGS += $(OS2_LDFLAGS) -EXTRA_DIST += bootstrap cfg.mk maint.mk .version .prev-version \ - $(config_macro_dir)/gnulib-cache.m4 -BUILT_SOURCES += .version -.version: - $(AM_V_GEN)echo $(VERSION) > $@-t && mv $@-t $@ -dist-hook: dist-tarball-version -dist-tarball-version: - $(AM_V_GEN)echo $(VERSION) > $(distdir)/.tarball-version - -dist-hook: $(changelog) -changelog_start_date = 2011-01-01 -$(changelog): FORCE - $(AM_V_GEN)if test -d '$(top_srcdir)/.git'; then \ - test -e '$(log_fix)' \ - && amend_git_log="--amend=$(log_fix)" \ - || amend_git_log=; \ - $(gitlog_to_changelog) $$amend_git_log \ - --since=$(changelog_start_date) > '$@T' \ - && rm -f '$@' && mv '$@T' '$@'; \ - fi - -# Sort in traditional ASCII order, regardless of the current locale; -# otherwise we may get into trouble with distinct strings that the -# current locale considers to be equal. -ASSORT = LC_ALL=C sort - -# Extract all lines up to the first one starting with "##". -prologue = perl -ne '/^\#\#/ and exit; print' $(no_thanks) - -# Generate THANKS using git log entries as far as possible, fixing -# up ommisions and errors from NO-THANKS configuration. -$(thanks): FORCE - $(AM_V_GEN)if test -d '$(srcdir)/.git'; then \ - { \ - $(prologue); echo; \ - { perl -ne '/^$$/.../^$$/ and print' $(no_thanks) \ - | grep -v '^$$' | perl -pe 's/ +/\0/'; \ - { sed -e '1,/\#\# /d' -e '/^\#\# /d' \ - -e 's|[ ][ ]*| |' < $(no_thanks) \ - | tr '\t' '\0'; \ - git log --pretty=format:'%aN%x00%aE'; \ - } | $(ASSORT) -u; \ - } | $(thanks_gen) \ - | LC_ALL=en_US.UTF-8 sort -f; \ - echo; \ - printf ';; %s\n' 'Local Variables:' 'coding: utf-8' End:; \ - } > '$@'; \ - fi - -MAINTAINERCLEANFILES += \ - ABOUT-NLS INSTALL Makefile.in aclocal.m4 \ - config-h.in configure stamp-h.in \ - po/cat-id-tbl.c po/m4.pot po/stamp-cat-id - - -## ------- ## -## GNU M4. ## -## ------- ## - -bin_PROGRAMS = src/m4 -src_m4_SOURCES = \ - src/assure.h \ - src/xstrtoul.c \ - src/xstrtol-error.c \ - src/xstrtol.c \ - src/xstrtol.h \ - src/version-etc-fsf.c \ - src/version-etc.c \ - src/version-etc.h \ - src/main.c \ - src/m4.h \ - src/freeze.c -if GETOPT -src_m4_SOURCES += \ - src/getopt.c \ - src/getopt1.c -endif -if STACKOVF -src_m4_SOURCES += src/stackovf.c -endif -src_m4_CPPFLAGS = $(AM_CPPFLAGS) -Isrc -I$(srcdir)/src -src_m4_LDADD = m4/libm4.la $(LTLIBICONV) $(LTLIBTHREAD) -src_m4_DEPENDENCIES = m4/libm4.la - -## ## -## --- PASTED MANUALLY FROM GNULIB --- ## -## To avoid adding unnecessary objects to libm4.la these gnulib ## -## modules are not imported by gnulib-tool, but added manually. ## -## (from: gnulib-tool --extract-automake-snippet getopt-posix) ## -## ## -if GETOPT -BUILT_SOURCES += src/$(GETOPT_H) -endif -EXTRA_DIST += src/getopt.c src/getopt1.c src/getopt.in.h src/getopt_int.h - -ARG_NONNULL_H = $(srcdir)/$(config_aux_dir)/arg-nonnull.h - -# We need the following in order to create an when the -# system doesn't have one that works with the given compiler. -src/getopt.h: src/getopt.in.h $(ARG_NONNULL_H) - $(AM_V_GEN)rm -f $@-t $@ && \ - { echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \ - sed -e 's|@''HAVE_GETOPT_H''@|$(HAVE_GETOPT_H)|g' \ - -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \ - -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \ - -e 's|@''NEXT_GETOPT_H''@|$(NEXT_GETOPT_H)|g' \ - -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ - < $(srcdir)/src/getopt.in.h; \ - } > $@-t && \ - mv -f $@-t $@ -MOSTLYCLEANFILES += src/getopt.h src/getopt.h-t -## ## -## --- END OF PASTED GNULIB --- ## -## ## - -## -------- ## -## Modules. ## -## -------- ## - -module_ldflags = -avoid-version -module $(AM_LDFLAGS) -module_libadd = m4/libm4.la - -noinst_HEADERS = modules/m4.h - -pkglib_LTLIBRARIES = - -pkglib_LTLIBRARIES += modules/gnu.la -EXTRA_modules_gnu_la_SOURCES = modules/format.c -modules_gnu_la_LDFLAGS = $(module_ldflags) -modules_gnu_la_LIBADD = $(module_libadd) -EXTRA_DIST += $(EXTRA_modules_gnu_la_SOURCES) - -pkglib_LTLIBRARIES += modules/m4.la -EXTRA_modules_m4_la_SOURCES = modules/evalparse.c -modules_m4_la_LDFLAGS = $(module_ldflags) -modules_m4_la_LIBADD = $(module_libadd) -EXTRA_DIST += $(EXTRA_modules_m4_la_SOURCES) - -if USE_GMP -pkglib_LTLIBRARIES += modules/mpeval.la -EXTRA_modules_mpeval_la_SOURCES = modules/evalparse.c -modules_mpeval_la_LDFLAGS = $(module_ldflags) -modules_mpeval_la_LIBADD = $(module_libadd) $(LIBADD_GMP) -endif - -pkglib_LTLIBRARIES += modules/stdlib.la -modules_stdlib_la_LDFLAGS = $(module_ldflags) -modules_stdlib_la_LIBADD = $(module_libadd) - -pkglib_LTLIBRARIES += modules/time.la -modules_time_la_LDFLAGS = $(module_ldflags) -modules_time_la_LIBADD = $(module_libadd) - -pkglib_LTLIBRARIES += modules/traditional.la -modules_traditional_la_LDFLAGS = $(module_ldflags) -modules_traditional_la_LIBADD = $(module_libadd) - - -## ----- ## -## libm4 ## -## ----- ## - -lib_LTLIBRARIES += m4/libm4.la - -nobase_include_HEADERS = \ - m4/m4module.h \ - m4/hash.h \ - m4/system.h -m4_libm4_la_SOURCES = \ - m4/builtin.c \ - m4/debug.c \ - m4/hash.c \ - m4/input.c \ - m4/m4.c \ - m4/m4private.h \ - m4/macro.c \ - m4/module.c \ - m4/output.c \ - m4/path.c \ - m4/resyntax.c \ - m4/symtab.c \ - m4/syntax.c \ - m4/utility.c -m4_libm4_la_LIBADD = m4/gnu/libgnu.la \ - $(LTLIBINTL) $(LIBADD_DLOPEN) -m4_libm4_la_DEPENDENCIES = m4/gnu/libgnu.la - -# This file needs to be regenerated at configure time. -dist-hook: - rm -f $(distdir)/m4/system.h -EXTRA_DIST += m4/system_.h - - -## -------------- ## -## Documentation. ## -## -------------- ## - -TAGS_FILES = $(infos_TEXINFOS) -TAGS_DEPENDENCIES = $(TAGS_FILES) -ETAGS_ARGS = --language=none --regex='/@node \([^,]*\)/\1/' $(TAGS_FILES) - -MAINTAINERCLEANFILES += $(dist_man_MANS) - -## --------- ## -## Examples. ## -## --------- ## - -EXTRA_DIST += \ - doc/examples/WWW/Makefile \ - doc/examples/WWW/_footer.htm \ - doc/examples/WWW/_header.htm \ - doc/examples/WWW/m4lib/bugs.m4 \ - doc/examples/WWW/m4lib/changelog.m4 \ - doc/examples/WWW/m4lib/download.m4 \ - doc/examples/WWW/m4lib/features.m4 \ - doc/examples/WWW/m4lib/feedback.m4 \ - doc/examples/WWW/m4lib/html.m4 \ - doc/examples/WWW/m4lib/index.m4 \ - doc/examples/WWW/m4lib/layout.m4 \ - doc/examples/WWW/m4lib/lists.m4 \ - doc/examples/WWW/m4lib/menu.m4 \ - doc/examples/WWW/m4lib/modules.m4 \ - doc/examples/WWW/m4lib/news.m4 \ - doc/examples/WWW/m4lib/readme.m4 \ - doc/examples/WWW/m4lib/setup.m4 \ - doc/examples/WWW/m4lib/test.m4 \ - doc/examples/WWW/m4lib/thanks.m4 \ - doc/examples/WWW/m4lib/thissite.m4 \ - doc/examples/WWW/m4lib/tmpl.m4 \ - doc/examples/WWW/m4lib/todo.m4 \ - doc/examples/WWW/m4lib/uses.m4 \ - doc/examples/WWW/m4lib/visions.m4 \ - doc/examples/WWW/m4lib/whatis.m4 - -dist_pkgdata_DATA = \ - doc/examples/capitalize.m4 \ - doc/examples/capitalize2.m4 \ - doc/examples/comments.m4 \ - doc/examples/curry.m4 \ - doc/examples/ddivert.m4 \ - doc/examples/debug.m4 \ - doc/examples/esyscmd.m4 \ - doc/examples/exp.m4 \ - doc/examples/foreach.m4 \ - doc/examples/foreach2.m4 \ - doc/examples/foreachq.m4 \ - doc/examples/foreachq2.m4 \ - doc/examples/foreachq3.m4 \ - doc/examples/foreachq4.m4 \ - doc/examples/forloop.m4 \ - doc/examples/forloop2.m4 \ - doc/examples/forloop3.m4 \ - doc/examples/fstab.m4 \ - doc/examples/hanoi.m4 \ - doc/examples/incl-test.m4 \ - doc/examples/incl.m4 \ - doc/examples/include.m4 \ - doc/examples/indir.m4 \ - doc/examples/join.m4 \ - doc/examples/loop.m4 \ - doc/examples/misc.m4 \ - doc/examples/multiquotes.m4 \ - doc/examples/patsubst.m4 \ - doc/examples/pushpop.m4 \ - doc/examples/quote.m4 \ - doc/examples/regexp.m4 \ - doc/examples/reverse.m4 \ - doc/examples/stack.m4 \ - doc/examples/stack_sep.m4 \ - doc/examples/sysv-args.m4 \ - doc/examples/trace.m4 \ - doc/examples/translit.m4 \ - doc/examples/undivert.incl \ - doc/examples/undivert.m4 \ - doc/examples/wrap.m4 \ - doc/examples/wrapfifo.m4 \ - doc/examples/wraplifo.m4 \ - doc/examples/wraplifo2.m4 - -EXTRA_DIST += \ - doc/examples/modtest.m4 \ - doc/examples/shadow.m4 \ - doc/examples/time.m4 \ - doc/examples/time2.m4 \ - doc/examples/stdlib.m4 - -## ----------- ## -## Test suite. ## -## ----------- ## - -# Use `$(srcdir)' for the benefit of non-GNU makes: this is -# how `testsuite' appears in our dependencies. -TESTSUITE = $(srcdir)/tests/testsuite -TESTSUITE_AT = \ - tests/builtins.at \ - tests/freeze.at \ - $(srcdir)/tests/generated.at \ - tests/macros.at \ - tests/modules.at \ - tests/options.at \ - tests/others.at \ - tests/testsuite.at - -EXTRA_DIST += $(TESTSUITE) $(TESTSUITE_AT) $(OTHER_FILES) \ - tests/atlocal.in \ - tests/generate.awk \ - $(srcdir)/tests/package.m4 - -module_check = -rpath /dev/null - -check_LTLIBRARIES += tests/import.la -tests_import_la_LDFLAGS = $(module_ldflags) $(module_check) -tests_import_la_LIBADD = $(module_libadd) - -check_LTLIBRARIES += tests/modtest.la -tests_modtest_la_LDFLAGS = $(module_ldflags) $(module_check) -tests_modtest_la_LIBADD = $(module_libadd) - -check_LTLIBRARIES += tests/shadow.la -tests_shadow_la_LDFLAGS = $(module_ldflags) $(module_check) -tests_shadow_la_LIBADD = $(module_libadd) - -# Using variables so that this snippet is not too wide and can -# be used as is in Texinfo @example/@end example. -m4_texi = $(srcdir)/doc/m4.texi - -generate = $(AWK) -f $(srcdir)/tests/generate.awk -$(srcdir)/tests/generated.at: tests/generate.awk $(m4_texi) - $(generate) $(m4_texi) >$@t - mv $@t $@ - -AUTOM4TE = $(SHELL) $(srcdir)/$(config_aux_dir)/missing --run autom4te -AUTOTEST = $(AUTOM4TE) --language=autotest -$(TESTSUITE): $(srcdir)/tests/package.m4 $(TESTSUITE_AT) - $(AUTOTEST) -I '$(srcdir)/tests' -o $@.tmp $@.at - mv $@.tmp $@ - -# The leading :; works around a bug in {}>f in some bash versions. -$(srcdir)/tests/package.m4: .version - :; \ - { \ - echo '# Signature of the current package.'; \ - echo 'm4_define([AT_PACKAGE_NAME], [$(PACKAGE_NAME)])'; \ - echo 'm4_define([AT_PACKAGE_TARNAME], [$(PACKAGE_TARNAME)])'; \ - echo 'm4_define([AT_PACKAGE_VERSION], [$(PACKAGE_VERSION)])'; \ - echo 'm4_define([AT_PACKAGE_STRING], [$(PACKAGE_STRING)])'; \ - echo 'm4_define([AT_PACKAGE_BUGREPORT], [$(PACKAGE_BUGREPORT)])'; \ - } > $(srcdir)/tests/package.m4 - -tests/atconfig: config.status - $(SHELL) ./config.status tests/atconfig -DISTCLEANFILES += tests/atconfig - -# Hook the test suite into the check rule -check-local: tests/atconfig tests/atlocal tests/m4 $(TESTSUITE) \ - $(check_LTLIBRARIES) - $(SHELL) '$(srcdir)/tests/testsuite' -C tests $(TESTSUITEFLAGS) - -# Run the test suite on the *installed* tree, including any renames -# the user requested. -installcheck-local: tests/atconfig tests/atlocal $(TESTSUITE) \ - $(check_LTLIBRARIES) - $(SHELL) '$(srcdir)/tests/testsuite' -C tests \ - AUTOTEST_PATH="$(bindir)" \ - M4="`echo m4 | sed '$(program_transform_name)'`" $(TESTSUITEFLAGS) - -# Enough users install GNU M4 as gm4 that we make sure 'make installcheck' -# will handle that, as part of making a release. -DISTCHECK_CONFIGURE_FLAGS = \ - --disable-assert \ - --program-prefix=g \ - --enable-cxx - -# We need to remove any file droppings left behind by testsuite. -clean-local-tests: - test ! -f '$(srcdir)/tests/testsuite' || \ - $(SHELL) '$(srcdir)/tests/testsuite' -C tests --clean - -OTHER_FILES = tests/iso8859.m4 tests/stackovf.test \ - tests/null.m4 tests/null.out tests/null.err - -DISTCLEANFILES += tests/atconfig tests/atlocal tests/m4 -MAINTAINERCLEANFILES += $(srcdir)/tests/generated.at '$(TESTSUITE)' - -clean-local: clean-local-tests - -FORCE: diff --git a/NEWS b/NEWS deleted file mode 100644 index 8c9b9865..00000000 --- a/NEWS +++ /dev/null @@ -1,1228 +0,0 @@ -GNU M4 NEWS - History of user-visible changes. -*- outline -*- - -* Noteworthy changes in Version 1.9b (201x-??-??) [beta] - Released by ????, based on git version 1.9a-* - -NOTE - there are still a number of FIXMEs to resolve before this can be -promoted to 2.0. - -** Building M4 - -*** The build environment has been updated to modern GNU practices, - depending on newer features of Autoconf, Automake, Libtool, Gettext, - and Gnulib to be more portable to a wide variety of platforms. - -** New command line behavior - -*** If the POSIXLY_CORRECT environment variable is set, it implies the - `-G' and `-Q' options, effectively giving a more fully POSIX-compliant - implementation with only compatible GNU extensions. - -*** New `-b'/`--batch' command-line option to force non-interactive mode. - Also, in addition to `-e'/`--interactive' requesting interactive mode, - m4 now follows the lead of sh, and automatically enters interactive - mode when there are no files specified, and when both standard input - and standard error are terminals. - -*** New `-B'/`--prepend-include' command-line option allows prepending to - the include path, rather than always searching `.' first. - -*** New `--debuglen' command-line option matches the spelling of a new - macro, and the old spelling `--arglength' now issues a warning that it - might be withdrawn in the future. - -*** The `-g'/`--gnu' command-line option is now required to allow all GNU - extensions when POSIXLY_CORRECT is set. - -*** The `-H'/`--hashsize' command-line options, which were made no-ops in - a previous beta, now issue a deprecation warning. - -*** The `-L'/`--nesting-limit' command-line option now performs argument - validation and accepts an optional multiplier suffix. - -*** New `-p'/`--pushdef' and `--popdef' command-line options allow more - control over macro definitions from the command line between input - files. - -*** New `--posix' command-line option is a synonym for `-G'/`--traditional'. - -*** New `-r'/`--regexp-syntax' command-line option changes the default - regular expression syntax used by M4. Without this option, M4 - continues to use EMACS style expressions. A new section in the info - docs explains the differences between them, and what builtins are - affected. - -*** New `--safer' command-line option cripples the potentially unsafe - builtins `debugfile', `esyscmd', `maketemp', `mkdtemp', `mkstemp', and - `syscmd'. - -*** New `--syncoutput' command-line option matches the builtin added in a - previous beta, and provides more control over sync line generation - from the command line between input files. The previous options - `-s'/`--synclines' remain as aliases for `--syncoutput=1'. - -*** New `--traceoff' command-line option, and new spelling `--traceon' for - `--trace', allow more control over macro tracing from the command line - between input files. - -*** New `--warnings' command-line option re-enables warnings, overriding - `-Q'/`--quiet'/`--silent', allowing warnings even when POSIXLY_CORRECT. - -*** When GNU extensions are enabled, any command line arguments that wauld - have been interpreted as input file names with previous releases are - still searched for as before, but will first attempt to be loaded as - compiled modules before falling back on loading as m4 input. In - POSIXLY_CORRECT mode, only m4 input files in the current directory can - be loaded. - -** POSIX conformance - -*** The `defn' builtin now allows any number of arguments, as POSIX requires. - - FIXME: This still doesn't work with concatenating builtins with text. - - - FIXME: POSIX recommends using ${10} instead of $10 for the tenth - positional argument. We should deprecate $10. - -** Removed builtins - -*** The experimental `epatsubst' and `eregexp' builtins have been removed - in favor of a new `changeresyntax' builtin. - -*** The `load' builtin, introduced in previous betas has been removed in - lieu of richer `include' and `sinclude' functionality. - -** New builtins - -*** New `changeresyntax' builtin allows programmatic setting of the default - regular expression flavor, to match `-r'/`--regexp-syntax' command-line - option. - -*** New `debuglen' builtin allows runtime setting of debug output length, - previously controlled only by the `-l' command line argument. - Additionally, whether using the new macro or the command line argument, - the length limitation now affects dumpdef output as well as trace - output, undergoes argument validation, and accepts an optional - multiplier suffix. - - FIXME the multiplier suffix isn't reliable yet - -*** New `mkdtemp' builtin parallels `mkstemp', but allows the creation of - temporary directories instead of files. - -*** New `refcount' builtin allows tracking how many times a module has - been loaded. - - FIXME: consider making m4modules smarter for this purpose - -*** New `renamesyms' builtin allows programmatic renaming of all symbols - according to a regular expression. - - FIXME: This feature can cause core dumps when renaming multiple - symbols to the same name. - -*** New `__traditional__' builtin identifies when the traditional module - is loaded instead of the gnu module. - -*** The `modules' and `symbols' builtins, introduced in previous betas, - have been renamed `m4modules' and `m4symbols', in order to minimize - problems when upgrading from 1.4.x and processing English text. To - prevent future problems, any future macro added as a GNU extension will - either be blind (ie. be unrecognized without arguments), or begin with - the prefix `m4' or `__'. - -** Changed behavior of builtins - -*** The module identifier builtins, such as `__gnu__', `__m4_version__', - and `__unix__', now warn if given arguments. - -*** The `builtin' builtin now has a special form, where if the first - argument is exactly the special token representing defn(`builtin'), the - expansion is the special token representing the builtin named in the - second argument. This allows regenerating a macro with a more - efficient mapping directly to a builtin function, rather than through - textual indirection through further expansions of `builtin'. - -*** The `changesyntax' builtin has been improved, to make it easier to add - and remove characters from a syntax class without having to specify the - entire set of characters in that class. It also supports new syntax - categories, `$', `{' and `}', for extended argument handling in macro - definitions. See the manual for more examples. - -*** New `m' flag to `-d'/`--debug' command-line option or `debugmode' - builtin traces actions related to module loading and unloading, and - affects `dumpdef' and trace output to show where builtins come from. - New `s' flag shows the entire stack of `pushdef' definitions during - `dumpdef'. The `c' flag has been updated to add information to the - first line to show the definition of the macro being expanded. - -*** The `eval' and `mpeval' builtins now support the following new - operators: `>>>', `\', and `,'. - -*** When GNU extensions are enabled, the `include' and `sinclude' builtins - continue to search directories one at a time, but will first attempt to - load arguments as compiled modules and then as m4 input before moving - to the next directory in the search path. In POSIXLY_CORRECT mode, - only m4 input in the current directory can be loaded. - -*** The `maketemp' builtin now always warns that it is obsolete, even in GNU - mode where it uses the same secure algorithm as `mkstemp', because of - the recommendation of POSIX to obsolete `maketemp' as inherently - insecure when obeying POSIX. - -*** The `m4symbols' builtin now warns if given a builtin token instead of - a macro name. It remains silent for undefined macros. - -*** The `patsubst' and `regexp' builtins have a new optional 4th argument - to use a different regular expression syntax for the duration of that - invocation. - -*** The semantics of the `traceon' and `traceoff' builtins now match - traditional implementations: when called without arguments, they affect - global state rather than affecting only the macros defined at that - moment. The manual includes an example of how to recover 1.4.x - semantics. - -** Other changes - -*** The syntax of frozen files format V2 has been improved to save - additional state. This includes the `R' directive for default regular - expression syntax, the `t' directive for traced macros, and the `d' - directive for debug mode. Existing directives with consecutive strings - now require an intermediate newline, for faster parsing. Also, a V2 - file can now be represented completely in ASCII, thanks to escape - sequences. Unfortunately, files frozen by M4 1.4q cannot be read by - 1.9b, but since 1.4q was not widely distributed, this is not expected - to be much of an issue, and comes with the territory of using a beta - release. - - FIXME: format 2 still needs to catch more missing state; once 2.0 is - released, any further changes would introduce format 3. - -*** Improvements made in the 1.4.x and 1.6 stable series have been - incorporated. - - -* Noteworthy changes in Version 1.6 (????-??-??) [stable] - Released by ????, based on git versions 1.4.10b.x-* and 1.5.* - -** 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'))'. - -** Fix regressions introduced in 1.4.10b: -*** Using `builtin' or `indir' to perform nested `shift' calls triggered - an assertion failure (not present in 1.4.11). -*** The command-line option -dV, as well as the builtin `debugmode(V)', - failed to enable `t' and `c' debug options (not present in 1.4.11). -*** Comments that contain unbalanced quotes were not rescanned correctly - when passed through $@ (not present in 1.4.11). -*** Using `defn' on a traced but undefined macro triggered an assertion - failure (also present in 1.4.11, but not 1.4.12). - -** Remove the undocumented command-line option '-N', as no one complained - about the assertion failure regression that it introduced in 1.4.7. - -** The `-o'/`--error-output' command-line options, which were replaced by - `--debugfile' in 1.4.7, now issue a deprecation warning. This warning - harmlessly triggers with versions of Autoconf 2.60 and earlier, but can - be silenced by applying this patch: - http://git.sv.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=714eeee87 - -** Fix the `m4wrap' builtin to accumulate wrapped text in FIFO order, as - required by POSIX. The manual mentions a way to restore the LIFO order - present in earlier GNU M4 versions. NOTE: this change exposes a bug - in Autoconf 2.59 and earlier (which was fixed in Autoconf 2.60). - - If you want your package to work with pre-installed Autoconf without - requiring 2.60, then add these lines to your project's configure.ac, - prior to calling AC_INIT: - - # As long as this project is not ready to upgrade to autoconf 2.60 - # or newer, make sure that newer M4 will still use LIFO order: - m4_define([m4_wrap], [m4_ifdef([_$0_text], - [m4_define([_$0_text], [$1]m4_defn([_$0_text]))], - [m4_define([_$0_text], [$1])m4_builtin([m4wrap], - [m4_default(m4_defn([_$0_text])m4_undefine([_$0_text]))])])]) - - On the other hand, if you want to install Autoconf 2.59 or earlier, - then apply this patch: - http://git.sv.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=56d42fa71 - -** The `changecom' builtin semantics now match traditional - implementations; if the start-comment string resembles a macro name or - the start-quote string, comments are effectively disabled. - -** The `divert' builtin now accepts an optional second argument of text - that is immediately placed in the new diversion, regardless of whether - the current expansion is nested within argument collection of another - macro. It has also been optimized for faster performance. - -** The `substr' builtin now treats negative arguments as indices relative - to the end of the string, and accepts an optional fourth argument of - text to supply in place of the selected substring. The manual gives an - example of how to recover M4 1.4.x behavior, as well as an example of - simulating the new negative argument semantics with older M4. - -** The `index' builtin now takes an optional third argument as the index - to begin searching from, with a negative argument relative to the end of - the string. - -** The `-d'/`--debug' command-line option now understands `-' and `+' - modifiers, the way the builtin `debugmode' has always done; this allows - `-d-V' to disable prior debug settings from the command line, similar to - using the builtin `debugmode' without arguments. The option - `--debugmode' is added as an alias for `-d'. The new flag `d' is added - to control whether dereferencing an undefined macro causes a warning; - this flag is enabled by default if neither `-d' nor `-E' are specified. - The new flag `o' is added to control whether `dumpdef' outputs to stderr - or the current `debugfile' location. When the command line option is - given the empty string, the mode is treated as `+adeq' instead of `aeq'. - Also, the position of `-d' with respect to files on the command line is - now significant. - -** A new predefined text macro, `__m4_version__', expands to the unquoted - version number of M4, if GNU extensions are enabled. While you should - generally favor feature tests over version number checks, this macro can - be used, via `defn', to determine whether the version of m4 processing - your file is adequate. - -** The `defn', `popdef', and `undefine' builtins gained a new warning when - operating on an undefined macro name, to match the warning already - present in `builtin', `indir', and `dumpdef'. For backwards - compatibility, the warning can be disabled by using `debugmode(`-d')' - (or the command line option `--debug=-d'). The flag is also cleared by - the command line option `-E'/`--fatal-warnings', so that scripts written - for 1.4.x do not cause the script to fail because of new warnings. - -** Enhance the `indir' builtin to trace indirect macros, where the trace - is requested via `traceon' or the command-line option `-t'. Previously, - it was impossible to trace macro names such as `foo-bar' which could - only be invoked indirectly, without relying on global tracing (such as - with `debugmode(`t')') or the experimental `changeword'. - -** Aspects of tracing output that were previously undocumented have been - slightly altered, and the effect of the builtin `debugmode' on trace - output is more fully documented. As POSIX does not specify trace output - format, parsing such output is inherently fragile in the first place. - The intent is that future M4 versions will not change documented trace - output without adding additional `debugmode' flags. - -** Enhance the `ifdef', `ifelse', and `shift' builtins, as well as all - user macros, to transparently handle builtin tokens generated by `defn'. - -** Allow the concatenation of builtin macros with arbitrary text in - several contexts, via the `defn' builtin or argument expansion, rather - than warning and converting the builtin token to an empty string. - However, it is still not possible to use a concatenated builtin when - defining a macro. - -** Enhance the `defn', `dumpdef', `ifdef', `popdef', `traceon', `traceoff', - and `undefine' macros to warn when encountering a builtin token in the - context of a macro name, rather than acting on the empty string. This - was already done for `define', `pushdef', `builtin', and `indir'. - -** Enhance the `eval' builtin to understand the `?:' operator, and - downgrade a failed parse due to an unknown operator from an error to a - warning. - -** A number of portability improvements inherited from gnulib. - -* Noteworthy changes in release 1.4.18 (2016-12-31) [stable] - -** Diagnose --word-regexp as unsupported if it was not configured. - -** Preliminary support for OS/2. - -** A number of portability improvements inherited from gnulib. - - -* Noteworthy changes in release 1.4.17 (2013-09-17) [stable] - -** Fix compilation with newer glibc headers. - -** Fix a failure with diverting large amounts of text on mingw (does - not affect platforms that can rename an open file). - -** A number of portability improvements inherited from gnulib. - - -* Noteworthy changes in release 1.4.16 (2011-03-01) [stable] - -** Fix regressions in the `index' builtin. On glibc platforms, this - avoids false positives from a strstr bug in glibc 2.9 through 2.12; - on many other platforms, it fixes two separate regressions, a false - positive introduced in 1.4.11 and a false negative in 1.4.15. - -** A number of portability improvements inherited from gnulib. - - -* Noteworthy changes in release 1.4.15 (2010-08-31) [stable] - -** Fix regression introduced in 1.4.9b where the `format' builtin could - crash on an invalid format string. - -** Fix compilation against newer glibc, and on AIX 7.1BETA. - -** A number of portability improvements inherited from gnulib. - -* Noteworthy changes in Version 1.4.14 (2010-02-24) [stable] - Released by Eric Blake, based on git version 1.4.13.* - -** Fix regression introduced in 1.4.12 where executing with stdout closed - could crash m4 on exit on some platforms. - -** Fix regressions introduced in 1.4.13 in the `esyscmd' builtin, where - closed file descriptors could interfere with child execution, and where - a child status of 127 made m4 print a spurious message to stderr. - -** A number of portability improvements inherited from gnulib. - -* Noteworthy changes in Version 1.4.13 (2009-04-01) [stable] - Released by Eric Blake, based on git version 1.4.12.* - -** The manual is now distributed under the terms of FDL 1.3. - -** The `divert' and `undivert' builtins have been made more efficient - when using temporary files for large diversions. - -** The `translit' builtin has been made more efficient when the second - argument is short. - -** The input engine has been optimized for faster processing. - -** The command line option `--debugfile', introduced in 1.4.7, now - treats its argument as optional, in order to allow setting the debug - output back to stderr when used without an argument; and order is now - significant with respect to command line files. You must therefore use - `m4 --debugfile=trace file', not `m4 file --debugfile trace'. This - change does not affect the deprecated `-o'/`--error-output' option. - -** The `syscmd' and `esyscmd' builtins can be configured to use an - alternate shell, via the new `configure' option `--with-syscmd-shell'. - -** A number of portability improvements inherited from gnulib. - -* Noteworthy changes in Version 1.4.12 (2008-10-10) [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'))'. - -** Fix regression introduced in 1.4.7 where `m4 -N9' died with an assertion - failure. - -** Fix regression introduced in 1.4.11 where `defn' died with an assertion - failure on a traced but undefined macro. - -** 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 (version 2.6 or newer recommended) 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 - -** Security fixes for the -F option, for bugs present since -F was - introduced in 1.3: Avoid core dump with 'm4 -F file -t undefined', and - avoid arbitrary code execution with certain file names. - -** Fix regression introduced in 1.4.9b in the `divert' builtin when more - than 512 kibibytes are saved in diversions on platforms like NetBSD - or darwin where fopen(name,"a+") seeks to the end of the file. - -** The output of the `maketemp' and `mkstemp' builtins is now quoted if a - file was created. This is a minor security fix, because it was possible - (although rather unlikely) that an unquoted string could match an - existing macro name, such that use of the `mkstemp' output would trigger - inadvertent macro expansion and operate on the wrong file name. - -** Enhance the `defn' builtin to support concatenation of multiple text - arguments, as required by POSIX. However, at this time, it is not - possible to concatenate a builtin macro with anything else; a warning is - now issued if this is attempted, although a future version of M4 may - lift this restriction to match other implementations. - -** Enhance the `format' builtin to parse all C99 floating point numbers, - even on platforms where strtod(3) is buggy, although the replacement - function does have the known issue of rounding errors when parsing - some decimal floating point values. This fixes testsuite failures - introduced in 1.4.9b. - -** Enhance the `index' builtin to guarantee linear behavior, in spite of - the surprisingly large number of systems with a brain-dead quadratic - strstr(3). - -** A number of portability improvements inherited from gnulib. - -* Noteworthy changes in Version 1.4.10b (2008-02-25) [beta] - Released by Eric Blake, based on git version 1.4.10a - -Note that M4 1.4.10b was released prior to 1.4.11, and includes all the -features of 1.4.11 except for C99 parsing in the `format' builtin. It also -contains the following beta features that were deemed worth deferring until -1.6: - -** Further enhance the `index' builtin to often achieve sublinear results. - -** Enhance the `regexp' and `patsubst' builtins to cache frequently used - regular expressions, which speeds up typical Autoconf usage. - -** Enhance the `format' builtin to warn for more suspicious usages, such as - missing arguments or problems parsing according to the format string. - -** Enhance the `ifelse' and `shift' builtins so that tail-recursive - algorithms based on `$@' operate in linear, rather than quadratic, time - and memory. - -** A number of portability improvements inherited from gnulib. - -* Noteworthy changes in Version 1.4.10 (2007-07-09) [stable] - Released by Eric Blake, based on CVS version 1.4.9c - -** Upgrade from GPL version 2 to GPL version 3 or later. - -** A number of portability improvements inherited from gnulib. - -** Avoid undefined behavior introduced in 1.4.9b in the `format' builtin - when handling %c. However, this area of code has never been documented, - and currently does not match the POSIX behavior of printf(1), so it may - have further changes in the next version. - -* Noteworthy changes in Version 1.4.9b (2007-05-29) [beta] - Released by Eric Blake, based on CVS version 1.4.9a - -** Fix regression introduced in 1.4.9 in the `eval' builtin when performing - division. - -** Fix regression introduced in 1.4.8 in the `-F' option that made it - impossible to freeze more than 512 kibibytes of diverted text. - -** The synclines option `-s' no longer generates sync lines in the middle of - multiline comments or quoted strings. - -** Work around a number of corner-case POSIX compliance bugs in various - broken stdio libraries. In particular, the `syscmd' builtin behaves - more predictably when stdin is seekable. - -** The `format' builtin now understands formats such as %a, %A, and %'hhd, - and works around a number of platform printf bugs. Furthermore, the - sequence format(%*.*d,-1,-1,1) no longer outputs random data. However, - some non-compliant platforms such as mingw still have known bugs in - strtod that may cause testsuite failures. - -** The testsuite is improved to also run gnulib portability tests for the - features that M4 imports from gnulib. - -* Noteworthy changes in Version 1.4.9 (2007-03-23) [stable] - Released by Eric Blake, based on CVS version 1.4.8c - -** Minor documentation and portability cleanups. - -* Noteworthy changes in Version 1.4.8b (2007-02-24) [beta] - Released by Eric Blake, based on CVS version 1.4.8a - -** Fix a regression introduced in 1.4.8 that made m4 unable to process - files larger than 2GiB on some platforms. - -** Fix a regression introduced in 1.4.8 that made m4 dump core when - invoked as 'm4 -- file'. - -** The `eval' builtin now follows C precedence rules. Additionally, the - short-circuit operators correctly short-circuit division by zero. The - previously undocumented alias of '=' meaning '==' in eval now triggers a - deprecation warning, so that a future version of M4 can implement a form - of variable assignment as an extension. - -** The `include' builtin now affects exit status on failure, as required by - POSIX. Use `sinclude' if you need a successful exit status. - -** The `-E'/`--fatal-warnings' command-line option now has two levels. When - specified only once, warnings affect exit status, but execution - continues, so that you can see all warnings instead of fixing them one - at a time. To achieve 1.4.8 behavior, where the first warning - immediately exits, specify -E twice on the command line. - -** A new `--warn-macro-sequence' command-line option allows detection of - sequences in `define' and `pushdef' definitions that match an optional - regular expression. The default regular expression is - `\$\({[^}]*}\|[0-9][0-9]+\)', corresponding to the sequences that might - not behave correctly when upgrading to the eventual M4 2.0. By default, - M4 2.0 will follow the POSIX requirement that a macro definition - containing `$11' must expand to the first argument concatenated with 1, - rather than the eleventh argument; and will take advantage of the POSIX - wording that allows implementations to treat `${11}' as the eleventh - argument instead of literal text. Be aware that Autoconf 2.61 will not - work with this option enabled with the default regular expression; but - Autoconf 2.62 will be compatible with this option. - -** Improved portability to platforms such as BSD/OS and AIX. - -* Noteworthy changes in Version 1.4.8 (2006-11-20) [stable] - Released by Eric Blake, based on CVS version 1.4.7a - -** The `divert' macro and `-H'/`--hashsize' command line option no longer - cause a core dump when handed extra large values. Also, `divert' now - uses memory proportional to the number of diversions in use, rather than - to the maximum diversion number encountered, so that large diversion - numbers are less likely to exhaust system memory; and is no longer - limited by the maximum number of file descriptors. - -** The `--help' and `--version' command line options now consistently - override all earlier options. For example, `m4 --debugfile=trace - --help' now no longer accidentally creates an empty file `trace'. - -** The `-L'/`--nesting-limit' command line option can now be set to 0 - to remove the default limit of 1024. However, it is still possible that - heavily nested input can cause abrupt program termination due to stack - overflow. - -** Problems encountered when writing to standard error, such as with the - `errprint' macro, now always cause a non-zero exit status. - -** Warnings and errors issued during macro expansion are now consistently - reported at the line where the macro name was detected, rather than - where the close parenthesis resides. Text wrapped by `m4wrap' now - remembers the location that was in effect when m4wrap was invoked, - rather than changing to line 0 and the empty string for a file. The - macros `__line__' and `__file__' now work correctly even as the last - token in an included file. - -** The `builtin' and `indir' macros now transparently handle builtin - tokens generated by `defn'. - -** When diversions created by the `divert' macro collect enough text that - M4 must use temporary files, the environment variable $TMPDIR is now - consulted, and a better effort is made to clean up those files in the - event of a fatal signal. - -** The `mkstemp' builtin is added with the same GNU semantics as `maketemp', - based on the recommendation of POSIX to deprecate the POSIX semantics of - `maketemp' as inherently insecure. In GNU mode (no -G supplied on the - command line), `maketemp' silently retains the secure GNU semantics, but - a future release of M4 will change this to emit a warning. In - traditional mode (m4 -G), `maketemp' now uses the POSIX-mandated - insecure semantics, and issues a warning that you should convert your - script to use `mkstemp' instead. Additionally, `mkstemp' and `maketemp' - are now well-defined even if the template argument does not end in six - `X' characters. - -** The manual has been improved, including a new section on a composite - macro `foreach'. - -** The `changecom' and `changequote' macros now treat an empty second - argument the same as if it were missing, rather than using the empty - string and making it impossible to end a comment or quote. - -** The `translit' macro now operates in linear instead of quadratic time, - and is now eight-bit clean. - -** The `-D', `-U', `-s', and `-t' command line options now take effect - after any files encountered earlier on the command line, rather than up - front, as is done in traditional implementations and required by POSIX. - -* Noteworthy changes in Version 1.4.7 (2006-09-25) [stable] - Released by Eric Blake, based on CVS version 1.4.6a - -** Fix regression from 1.4.5 in handling a file that ends in a macro - expansion without arguments instead of a newline. - -** The define and pushdef macros now warn when the first argument is not - a string, rather than silently doing nothing. - -** Standard input can now be read more than once, as in 'm4 - file -', and - is not closed until all wrapped text is handled. This makes a - difference when stdin is not a regular file, and also fixes bugs when - using the syscmd or esyscmd macros from wrapped text. - -** When standard input is a seekable file, the m4exit, syscmd, and esyscmd - macros now restore the current position to the next unread byte rather - than discarding an arbitrary amount of buffered data. - -** SysV command-line compatibility is no longer a goal of GNU M4; the - focus will be instead on POSIX compatibility. This release continues to - support previous usage, but adds warnings in areas which will allow a - future version of GNU M4 to use its own extensions without being tied to - the SysV command line interface. - -** The no-op compatibility command line options -B, -N, -S, -T, and - --diversions may be withdrawn or assigned new meanings in future - releases, so they now issue a warning if used. - -** A new command line option -i replaces the compatibility -e as the - short spelling of --interactive, for consistency with other GNU tools; a - warning is issued if the old spelling is used, and it may be assigned - new meaning in future releases. - -** A new command line option --debugfile replaces the options -o and - --error-output as the preferred spelling. The old options were - misleading in their names and inconsistent with other GNU tools; they - are still silently accepted, but no longer documented in --help, and may - be assigned new meanings in future releases. - -* Noteworthy changes in Version 1.4.6 (2006-08-25) [stable] - Released by Eric Blake, based on CVS version 1.4.5a - -** Fix buffer overruns in regexp and patsubst macros when handed a trailing - backslash in the replacement text, or when handling \n substitutions - beyond the number of \(\) groups. - -** Fix memory leak in regexp, patsubst, and changeword macros. - -** The format macro now understands %F, %g, and %G. - -** When loading frozen files, m4 now exits with status 63 if version - mismatch is detected. - -** Fix bugs that occurred when invoked with stdout or stderr closed, - and detect write failures to stdout or to the target of the debugfile - macro. In particular, the syscmd and esyscmd macros can no longer - interfere with the debug stream or diversions. - -** The m4exit macro now converts values outside the range 0-255 to 1. - -** It is now an error if a command-line input file ends in the middle of a - comment, matching the behavior of mid-string and mid-argument - collection. - -** The dnl macro now warns if end of file is encountered instead of a - newline. - -** The error message when end of file is encountered now uses the file and - line where the dangling construct started, rather than `NONE:0:'. - -** The debugmode and __file__ macros, and the -s/--synclines option, now - show what directory a file was found in when the -I/--include option or - M4PATH variable had an effect. - -** The changequote and changecom macros now work with 8-bit characters, and - quotes and comments that begin with `(' are properly recognized - following a word. - -** The new macro __program__ is added, which allows the input file to issue - an error message that resembles messages from m4. Warning and error - messages have been reformatted to comply with GNU Coding Standards. - -** The errprint, m4wrap, and shift macros are now recognized only with - arguments. - -** The index, substr, translit, regexp, and patsubst macros now produce - output when given only one argument, but still warn about a missing - second argument. - -** The patsubst macro now reliably finds zero-length matches at the end - of a string. - -* Noteworthy changes in Version 1.4.5 (2006-07-15) [stable] - Released by Eric Blake, based on CVS version 1.4.4c - -** Fix sysval on BeOS, OS/2, and other systems that store exit status - in the low-order byte. Additionally, on Unix platforms, if syscmd was - terminated by a signal, sysval now displays the signal number shifted - left by eight bits, to match traditional m4 implementations. - -** The maketemp macro is no longer subject to platform limitations (such as - 26 or 32 max files from a given template). - -** Frozen files now require that the first directive be V (version), to - better diagnose version mismatch. Additionally, if the F directive - (builtin function) names an unknown builtin that existed in the m4 that - froze the file but not in the current m4 (for example, changeword), the - warning is deferred until an attempt is made to actually use the - builtin. This allows downgrading from beta m4-1.4o to stable m4-1.4.5 - without breaking autoconf. - -** The format and indir macros are now recognized only with arguments. - -** The eval macro no longer crashes on x86 architectures when dividing the - minimum integer by -1. - -** On systems with ecvt and fcvt, format no longer truncates trailing - zeroes on integers printed with %.0f. On systems without these - functions, format is no longer subject to a buffer overflow that - permitted arbitrary code execution. - -** On native Windows builds, the macro __windows__ is provided instead of - __unix__. Likewise, on OS/2 builds, the macro __os2__ is provided. - This allows input files to determine when syscmd might behave - differently. - -** Fix bug in 1.4.3 patch to use \n line-endings that did not work for - cygwin. - -** When given the empty string or 0, undivert is now documented as a no-op - rather than closing stdout, warning about a non-existent file, or trying - to read a directory as a file. - -** Many documentation improvements. Also, the manual is now distributed - under FDL 1.2, rather than a stricter verbatim-only license. - -** Raise the -L (--nesting-limit) command line option limit from 250 to - 1024. - -** The decr, incr, divert, m4exit, and substr macros treat an empty number - as 0, issue a warning, and expand as normal; rather than issuing an - error and expanding to the empty string. - -** The eval macro now treats an empty radix argument as 10, handles radix 1, - and treats the width argument as number of digits excluding the sign, - for compatibility with other m4 implementations. - -** The ifdef, divert, m4exit, substr, and translit macros now correctly - ignore extra arguments. - -** The popdef and undefine macros now correctly accept multiple arguments. - -** Although changeword is on its last leg, if enabled, it now reverts to the - default (faster) regexp when passed the empty string. - -** The regexp and substr macros now warn and ignore a trailing backslash in - the replacement, and warn on \n for n larger than the number of - sub-expressions in the regexp. - -* Noteworthy changes in Version 1.4.4b (2006-06-17) [beta] - Released by Eric Blake, based on CVS version 1.4.4a - -** Fix a recursive push_string crashing bug, which affected changequote of - three or more characters on some compilers. - -** Use automake to fix build portability issues. - -** Fix a recursive m4wrap crashing bug. - -** Fix a 1 in 2**32 hash crashing bug. - -** Tracing a macro by name is now persistent, even if the macro is - subsequently undefined or redefined. The traceon and traceoff macros no - longer warn about undefined symbols. This solves a crash when using - indir on an undefined macro traced with the -t option, as well as an - incorrect result of ifdef. Furthermore, tracing is no longer - transferred with builtins, solving the bug of "m4 -tm4_eval" failing to - give trace output on the input - "define(`m4_eval',defn(`eval'))m4_eval(1)". - -** Fix a crash when a macro is undefined while collecting its arguments, by - always using the definition that was in effect before argument - collection. This behavior matches the C pre-processor, and means that - the sequence "define(`f',`1')f(define(`f',`2'))f" is now documented to - result in "12", rather than the previously undocumented "22". - -** Update the regex engine to fix several bugs. - -** Fix a potential crash on machines where char is signed. - -* Noteworthy changes in Version 1.4.4 (Oct 2005) [stable] - Released by Gary V. Vaughan - -** ./configure --infodir=/usr/share/info now works correctly. - -** When any file named on the command line is missing exit with status 1. - -* Noteworthy changes in Version 1.4.3 (Mar 2005) [stable] - Released by Gary V. Vaughan - -** DESTDIR installs now work correctly. - -** Don't segfault with uncompilable regexps to changeword(). - -** Always use \n line-endings for frozen files (fixes a Windows bug). - -** Portability fix for systems lacking mkstemp(3). - -** Approximately 20% speed up in the common case of usage with autoconf. - -** Supported on QNX 6.3. - -* Noteworthy changes in Version 1.4.2 (Aug 2004) [stable] - Released by Paul Eggert - -** No user visible changes; portability bug fixes only. - -* Noteworthy changes in Version 1.4.1 (Jun 2004) [stable] - Released by Paul Eggert - -** The 1.4.x series is intended to be stable; features added in 1.4[a-q] - were not backported to 1.4.x unless specifically mentioned above. - -** maketemp now creates an empty file with the given name, instead of merely - returning the name of a nonexistent file. This closes a security hole. - - -* Version beta 1.4q - August 2001, by Gary V. Vaughan - -** Support for the experimental `changeword' has been dropped. - -** `m4 --hashsize' and `-H' are still accepted, but have no effect. M4 - will grow its internal symbol table if the symbol density is having an - effect on performance. - -** `configure --without-modules' will build an m4 binary with no preloaded - modules. At startup it will search for and load modules `m4' and either - `gnu' or `traditional'. This mode of operation can be used for - development and debugging of the base modules without the need to - recompile all of m4 with each modification. - -** `configure --with-modules="gnu m4 traditional load"', for example, - will build an m4 binary with the named modules preloaded, ready to be - activated (even on static lib only machines) with the `-m' option or - using the `load' builtin. - -** M4 has no builtins or macros in core, they are all loaded from modules - at startup. This means that modules are no longer optional, though the - standard build will statically link the modules `m4', `gnu' and - `traditional', so even on machines with no ltdl support, all of the - functionality from previous releases is available. - -** New builtin `load' to dynamically load modules which can define new - builtins and user macros. - -** New builtin `unload' to remove loaded modules (and the builtins and user - macros they define) from the running m4 interpreter. - -** New builtins `eregexp' and `epatsubst' to use Extended Regular - Expressions syntax in lieu of Basic Regular Expressions as used by - `regexp' and `patsubst'. - -** The names of all currently loaded modules are returned by the new - builtin, ``modules''. - -** Loadable modules can define new builtin functions or text expansion - macros. - -** The module code has been rewritten to use libltdl, the libtool dynamic - loader, which means GNU m4 can now load (and unload) modules just about - anywhere which it can be built. This includes obscure hosts such as - cygwin and BeOS, and also on hosts which do not have shared libraries, - through preloading (see libtool manual) and GNU dld. - -** Modules can now be built without the m4 source being available using the - installed m4module.h header file (and some other headers that it - includes for you), and the installed libm4.la libtool library. All - symbols exported from libm4.la have a prefix of `m4_' or `M4_'. See the - modules directory for examples of usage. - -** A new V2 format for frozen files that saves module and syntax information. - -* Version beta 1.4o - January 2000, by Rene' Seindal - -** Modules can be loaded from the command line with --load-module - -** Modules now use libtool's wrapper libltdl. - -** New builtin `symbols' allows dynamic queries of all currently defined - macros. - -** Various Bug fixes. - -* Version beta 1.4n - November 1998, by Rene' Seindal - -** The module code has been reorganised yet again, and now compiles - correctly on GNU/Linux, HPUX 9 and 10, SunOS 5 and Solaris 5. - -** When configured --with-gmp a new builtin `mpeval' is now defined. The - builtin `eval' retains its normal behaviour. - -** m4 --version also shows which options were used for compilation, such as: - "GNU m4 1.4n (options: modules gmp changeword)" - -** New option --import-environment defines all environment variables as - macros. This is done before -D and -U are handled, so the macros can be - changed through these options. - -** Error messages now always print program name before input file name as - specified by GNU coding standards. Reported by Akim Demaille. - -** Bug fixed: "undivert(0)" could cause m4 to read standard output. A call - of "undivert(0)" is now silently ignored. - -** Bug fixed: when compiling --with-included-gettext, wasn't - found in intl/ directory. Reported by Andrew Bettison. - -* Version beta 1.4m - November 1998, by Rene' Seindal - -** Using libtool for compiling modules and for linking main app. - -** Reorganised the dynamic module code to encapsulate system dependencies - better. The code for HPUX shl_load() still needs testing and debugging. - A dld interface is also missing. Any volunteers? - -** The files from the GNU m4 web-site is now in examples/WWW as a more - complete example of what GNU m4 can do. - -* Version beta 1.4l - November 1998, by Rene' Seindal - -** GNU m4 now has an escape syntax category. If a character is marked as - an escape, words are only recognised as macros if preceded by an escape - character. It is a bit like -P, but dynamic: it can be turned on and - off. The GNU m4 web-site on http://www.seindal.dk/rene/gnu/ is - maintained with this feature - the m4 source is available on the site. - -** The module interface is improved, thanks to "Brian J. Fox", - who has contributed some code from Meta-HTML. The modules now build - automatically and installs properly, by default in - /usr/local/libexec/m4. There is a preliminary, untested support for - shl_load(). - -** There is now a __m4_version__ macro that expands to the current version - number. - -* Version beta 1.4k - November 1998, by Erick Branderhorst and Rene' Seindal - -** GNU m4 now uses gettext to support internationalization. - -** GNU m4 now uses automake to control Makefile.in generation. This - should make it more consistent with the GNU standards. - -** GNU m4 will use the gmp library for multiple precision integral and - rational arithmetic in `eval' if configured with `--with-gmp'. If - configured without `--with-gmp' or if gmp is not available, and the type - `long long int' is, GNU m4 will use that for `eval' arithmetic. - -** GNU m4 now parses the input according to a syntax table, that can be - modified through the new builtin `changesyntax'. It is a generalisation - of the existing builtins `changecom' and `changequote'. The changes are - completely backwards compatible (except for the existence of - `changesyntax'). - -** Sync lines can be turned on and off with the `syncoutput' builtin. The - builtin `syncoutput' is a GNU extension. - -** New experimental feature: dynamically loadable modules. New builtin - `loadmodules' loads shared libraries, that can define new builtin - macros, ie, new macros can be written in C. Depends on the dlopen() - interface, and is currently only tested on Linux. Enabled at configure - time with `--with-modules'. Documentation is in src/module.c and - module/README. - -** Implement a GNU message catalog for French (Franc,ois Pinard). - -** Filenames found through path searches are now correctly reflected in - error and debug messages and through the `__file__' macro. - -** Bugs fixed: - -*** All 8-bit characters can now be used for quotes. - -* Version 1.4 - October 1994, by Franc,ois Pinard - -** (No user visible changes) - -* Version 1.3 - September 1994, by Franc,ois Pinard - -** Diversions are created as needed. Option `-N' is still accepted, but - otherwise ignored. Users should use only negative diversion numbers, - instead of high positive numbers, for diverting to nowhere. - -** Diversions should also work faster. No temporary files will be needed - at all if all diversions taken altogether do not use more than 512K. - -** Frozen state files may be produced with the `--freeze-state' (-F) - option and later brought back through the `--reload-state' (-R) option. - -* Version 1.2 - July 1994, by Franc,ois Pinard - -** In patsubst(STRING, REGEXP, REPLACEMENT), \& in REPLACEMENT has been - changed to represent this part of STRING matched by the whole REGEXP, - instead of the whole STRING as before. \0 does the same, but emits a - diagnostic saying it will disappear in some subsequent release. - -** eval(EXPR) emits a diagnostic if EXPR has suffixed crumb. The same for - other numeric conversions in incr(), decr(), divert(), etc. - -** `--fatal-warnings' (-E) stops execution at first warning. - -** `--nesting-limit=LEVEL' (-L LEVEL) sets a limit to macro nesting. - It is initially fixed at 250. - -** `--word-regexp=REGEXP' (-W REGEXP) modifies macro name syntax, like - does the new `changeword(REGEXP)' macro. This feature is experimental, - tell me your opinions about it. You do need --enable-changeword at - configure time to get these things. Do *not* depend on them yet. - -** Trace output format is scannable by GNU Emacs' next-error function. - -** Stack overflow is detected and diagnosed on some capable systems. - -** Various bugs have been corrected, m4 should be more portable. See the - ChangeLog for details. - -* Version 1.1 - November 1993, by Franc,ois Pinard - -** Changes which might affect existing GNU m4 scripts: - -*** Option `-V' has been removed, use `--version' instead. `--version' - writes on standard output instead of standard error, and inhibits any - script execution. - -*** `--no-gnu-extensions' has been renamed `--traditional'. - -*** In `eval', `^' used to indicate exponentiation, use `**' instead. - -*** The automatic undiversion which takes place at end of all input is - forced into the main output stream. - -** Changes which are unlikely to affect existing scripts: - -*** `--help' prints an usage summary on standard output. Script execution - is then inhibited. - -*** `--prefix-builtins' (-P) prefixes all builtin macros by `m4_'. - -*** Most builtin macros for which arguments are mandatory, called without - any arguments, are no more recognized as builtin macros: they are - consequently copied verbatim to the output stream. - -*** `define' and `pushdef' are usable with only one argument, they give - this argument an empty definition. - -*** `eval' new operators for binary representation handling: `^' for - exclusive-or, `~' for the bitwise negation, `<<' and `>>' for shifts. - -*** `eval' recognizes the notation 0bDIGITS for binary numbers and the - notation 0rRADIX:DIGITS for numbers in any radix from 1 to 36. - -* Version 1.0.3 - December 1992, by Franc,ois Pinard - -** Changes for the user: - -*** `dnl' outputs a diagnostic if immediately followed by `('. Usually, - `dnl' is followed by newline or whitespace. - -*** `ifelse' accepts without complaining the common idiom of having only - one argument. This is useful for introducing long comments. - -*** `eval' always expresses values as signed, whatever the radix. - -*** M4OPTS environment variable is no longer obeyed. - -*** `--no-warnings' option is renamed `--silent'. - -*** Debug lines use a new format more compatible with GNU standards. - -*** Various bugs have been corrected. See the ChangeLog for details. - -** Changes for the installer: - -*** GNU m4 now uses an Autoconf-generated configure script, and should be - more easily portable in many ways. (Cray is not supported yet). - -*** `make check' has been made more portable, expect no errors. - -** Changes for the programmer: - -*** Sources have been fully reindented to comply with GNU standards, and - cleaned up in many ways. - -*** Sources have been protoized. Non-ANSI compilers are automatically - detected, then sources are unprotoized on the fly before compilation. - -*** GNU m4 uses newer versions of obstack, regex, getopt, etc. - -* Version 1.0 - October 1991, by Rene' Seindal - -** Uses GNU configure, taken from the gdb distribution. - -** Uses GNU getopt(), with long option names. - -** The -Q/+quiet option is added, which suppresses warnings about missing - or superflous arguments to builtin macros. - -** Added default options via the M4OPTS environment variable. - -** Several minor bugs have been fixed. - -* Version 0.99 - July 1991, by Rene' Seindal - -** The builtins `incr' and `decr' are now implemented without use of - `eval'. - -** The builtin `indir' is added, to allow for indirect macro calls - (allows use of "illegal" macro names). - -** The debugging and tracing facilities has been enhanced considerably. - See the manual for details. - -** The -tMACRO option is added, marks MACRO for tracing as soon as it - is defined. - -** Builtins are traced after renaming iff they were before. - -** Named files can now be undiverted. - -** The -Nnum option can be used to increase the number of divertions - available. - -** Calling changecom without arguments now disables all comment handling. - -** A bug in `dnl' is fixed. - -** A bug in the multi-character quoting code is fixed. - -** Several typos in the manual has been corrected. More probably persist. - -* Version 0.75 - November 1990, by Rene' Seindal - -** Implemented search path for include files (-I option and M4PATH - environment variable). - -** Implemented builtin `format' for printf-like formatting. - -** Implemented builtin `regexp' for searching for regular expressions. - -** Implemented builtin `patsubst' for substitution with regular - expressions. - -** Implemented builtin `esyscmd', which expands to a shell commands output. - -** Implemented `__file__' and `__line__' for use in error messages. - -** Implemented character ranges in `translit'. - -** Implemented control over debugging output. - -** Implemented multi-character quotes. - -** Implemented multi-character comment delimiters. - -** Changed predefined macro `gnu' to `__gnu__'. - -** Changed predefined macro `unix' to `__unix__', when the -G option is - not used. With -G, `unix' is still defined. - -** Added program name to error messages. - -** Fixed two missing null bytes bugs. - -* Version 0.50 - January 1990, by Rene' Seindal - -* Initial beta release. - -======================================================================== - -Local Variables: -fill-column: 75 -End: - -Copyright (C) 1992-1994, 2004-2011, 2013-2014, 2017 Free Software -Foundation, Inc. - -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.3 or -any later version published by the Free Software Foundation; with no -Invariant Sections, with no Front-Cover Texts, and with no Back-Cover -Texts. A copy of the license is included in the ``GNU Free -Documentation License'' file as part of this distribution. diff --git a/NO-THANKS b/NO-THANKS deleted file mode 100644 index 87d631e6..00000000 --- a/NO-THANKS +++ /dev/null @@ -1,186 +0,0 @@ -These people have contributed to GNU M4. Some have reported problems, -others have contributed improvements to the documentation and actual code. -The particular contributions are described in the version control logs and -ChangeLog files. If your name has been left out, if you'd rather not be -listed, or if you'd prefer a different address be used, please send a -note to the bug-report mailing list (as seen at end of e.g., m4 --help). -## -## There is no need to list here any name that appears as an Author in -## "git log" output. Those are automatically added when this template -## is used to generate the THANKS file. You will still need to add -## contributors who are not a git log Author - e.g. bug reporters. -## -## Folks already promoted to AUTHORS: -## -!Akim Demaille -!Alexandre Duret-Lutz -!Andrew James Bettison -!David Warme -!Eric Benjamin Blake -!François Pinard -!Gary V. Vaughan -!James L. Avera -!Joel E. Denny -!John Brzustowski -!John Gatewood Ham -!John Gerard Makecki -!Markus Duft -!Michael Elizabeth Chastain -!Noah Jeffrey Misch -!Pete Chown -!Ralf Wildenhues -!Raphael Poss -!RenĂ© Seindal -!Thomas Tanner -!Tim Rice -!William C. Cox -!Yuji Minejima -## -## Remove duplicates under alternate names, and add preferred email -## addresses from contributors that don't match git log output here: -## -!Andrew Bettison -!Eric Blake -!Francois Pinard -!Noah Misch -!Rene' Seindal -## -## Add bug reporters, patch Authors you forgot to attribute at commit -## time with 'git commit --author=...' and other non-patch contributers -## below: -## -Akiko Matsushita matusita@sra.co.jp -Alan Magnuson awm@osc.edu -Albert Chin m4-discuss@mlists.thewrittenword.com -Alexander Lehmann alex@hal.rhein-main.de -Amos Shapira amoss@cs.huji.ac.il -Andreas BĂ¼ning andreas.buening@nexgo.de -Andreas Gustafsson gson@niksula.hut.fi -Andreas Schultz aschultz@warp10.net -Andreas Schwab schwab@ls5.informatik.uni-dortmund.de -Andrew Athan athan@morgan.com -Assar Westerlund assar@nada.kth.se -Ben A. Mesander ben@piglet.cr.usgs.gov -Ben Elliston bje@cygnus.com -Bengt Mertensson bengt@mathematik.uni-bremen.de -Bernhard Daeubler daeb@physik.uni-ulm.de -Bill Bumgarner bbum@thoughtport.com -Bjorn R. Bjornsson brb@falcon.is -Bob Badour bob@badour.net -Bob Proulx bob@proulx.com -Brendan Kehoe brendan@cygnus.com -Brian J. Fox bfox@datawave.net -Brian D. Carlstrom bdc@clark.lcs.mit.edu -Cesar Strauss cestrauss@gmail.com -Charles Wilson cygwin@cwilson.fastmail.fm -Chris McGuire chris@wso.net -Chris Penev xpenev@gmail.com -Damian Menscher menscher@uiuc.edu -Dan Jacobson jidanni@jidanni.org -Daniel Richard G. skunk@iskunk.org -David J. MacKenzie djm@uunet.uu.net -David Perlin davep@nanosoft.com -Elbert Pol elbert.pol@gmail.com -Elias Benali elptr@users.sourceforge.net -Erez Zadok ezk@cs.columbia.edu -Eric Allman eric@cs.berkeley.edu -Eric Backus ericb@lsid.hp.com -Eric Fischer enf1@ellis.uchicago.edu -Erick Branderhorst Erick.Branderhorst@asml.nl -Fernando Carrijo fcarrijo1980@gmail.com -Frank Schwidom schwidom@impernet.de -Gary Affonso Gary_Affonso@iqinc.com -Geoff Russell grussell@guest.adelaide.edu.au -Giovanni Toffetti toffettg@lu.unisi.ch -Greg A. Woods woods@web.apc.org -Greg McGary gkm@cstone.net -Hal Peterson hrp@pecan.cray.com -Hoang Uong hoang@ornews.intel.com -Hongjiu Lu hjl@nynexst.com -Ian Taylor ian@cygnus.com -Ilya N. Golubev gin@mo.msk.ru -Jan Djarv Jan.Djarv@sa.erisoft.se -Jason Merrill jason@jarthur.claremont.edu -Jay Krell jay.krell@cornell.edu -Jean-Charles Longuet jclonguet@free.fr -Jens Rehsack rehsack@googlemail.com -Jim Avera jima@netcom.com -Jim Kingdom kingdon@cygnus.com -Jim Meyering meyering@acm.org -Joel Sherrill jsherril@uahcs2.cs.uah.edu -John David Anglin dave@hiauly1.hia.nrc.ca -Josef T. Burger bolo@bolo.com -Joseph E. Sacco jsacco@ssl.com -Joseph S. Myers jsm28@cam.ac.uk -Joshua R. Poulson jrp@plaza.ds.adp.com -Karl Berry karl@freefriends.org -Karl Nelson nelson85@llnl.gov -Karl Vogel vogelke@c-17igp.wpafb.af.mil -Kaveh R. Ghazi ghazi@noc.rutgers.edu -Keith Bostic bostic@abyssinian.sleepycat.com -Konrad Schwarz konrad.schwarz@siemens.com -Kristine Lund lund@lpnaxp.in2p3.fr -Krste Asanovic krste@icsi.berkeley.edu -Lawson Chan Lawson.Chan@tdsecurities.com -M. Levinson levinsm@users.sourceforge.net -Marcus Daniels marcus@ee.pdx.edu -Marion Hakanson hakanson@cse.ogi.edu -Mark Seiden mis@seiden.com -Martin Koeppe mkoeppe@gmx.de -Massimo Dal Zotto dz@cs.unitn.it -Matt Kraai kraai@debian.org -Matthew Woehlke mw_triad@users.sourceforge.net -Matthias Rabe rabe@mathematik.uni-bielefeld.de -Mehul Sanghvi mehul.sanghvi@gmail.com -Michael Fetterman mafetter@ichips.intel.com -Michael L. Welcome welcome@bigbird.llnl.gov -Mike Andrews kramer@fragile.termfrost.org -Mike Dupont jamesmikedupont@googlemail.com -Mike Frysinger vapier@gentoo.org -Mike Howard mike@clove.com -Mike Lijewski lijewski@theory.tc.cornell.edu -Mike R. mroberge@aol.com -Mike Stump mikestump@comcast.net -Mikhail Teterin Mikhail.Teterin@murex.com -Nelson H. F. Beebe beebe@math.utah.edu -Nick S. Kanakakorn skanan@otl.scu.edu -Nicolas Lichtmaier nick@technisys.com.ar -Nicolas Pioch pioch@inf.enst.fr -Noah Friedman friedman@gnu.org -Per Bothner per@bothner.com -Pierre Gaumond gaumondp@ere.umontreal.ca -Pierre Mathieu mathieu@geod.emr.ca -Rafael Corvalan rafael@club-internet.fr -Rainer Tammer tammer@tammer.net -Richard A Nelson cowboy@vnet.ibm.com -Richard Ling richard@research.canon.oz.au -Richard Stallman rms@gnu.org -Robert Bernstein rocky@panix.com -Robert Bihlmeyer robbe@orcus.priv.at -Roderick Koehle Roderick.Koehle@infineon.com -Roland H. Pesch roland@wrs.com -Roland McGrath roland@gnu.org -Ronny Peine RonnyPeine@gmx.de -Sami Liedes sliedes@cc.hut.fi -Santiago Vila sanvila@debian.org -Scott Bartram deneb!scottb -Sergey Poznyakoff gray@gnu.org.ua -Simon Leinen simon@lia.di.epfl.ch -Skip Montanaro skip@automatrix.com -Stephen Perkins perkins@cps.msu.edu -Steve Williamson willy@uinpla.npl.uiuc.edu -Steven Augart saugart@yahoo.com -Terry Jones terry@cliffs.ucsd.edu -Thomas Klausner tk@giga.or.at -Thorsten Ohl ohl@physics.harvard.edu -Todd Rinaldo toddr@cpanel.net -Tom G. Christensen tgc@jupiterrise.com -Tom McConnell tmcconne@sedona.intel.com -Tom Quinn trq@dionysos.thphys.ox.ac.uk -Tom Tromey tromey@cns.caltech.edu -Ulrich Drepper drepper@gnu.org -Vern Paxson vern@ee.lbl.gov -Vic Abell abe@cc.purdue.edu -Vincent Lonngren Vincent.lonngren.759@student.lu.se -Vivek P. Singhal singhal@cs.utexas.edu -Walter Wong wcw+@cmu.edu diff --git a/README b/README index 69255a21..f228134e 100644 --- a/README +++ b/README @@ -9,92 +9,20 @@ GNU `m4' was originally written by Rene' Seindal, from Denmark. GNU `m4' has a web site at http://www.gnu.org/software/m4/. -If GNU `m4' is meant to serve GNU `autoconf', beware that `m4' -should be fully installed *prior to* configuring `autoconf' itself. -Likewise, if you intend on hacking GNU `m4' from git, the bootstrap -process requires that you first install a released copy of GNU `m4'. - -If you are just trying to build `m4' from a released tarball, you -should not normally need to run `./bootstrap' or `autoreconf'; just go -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. - -In the subdirectories `tests' and `doc/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. - -See file `COPYING' for copying conditions. Note that M4 is distributed -under the GNU Public License version 3 or later. Some files in the -distribution are copied from the gnulib project, and hence bear the -designation version 2 or later because they are unmodified from gnulib; -however, if you modify these files using M4 rather than gnulib as the -source, you must update the license to be GPLv3 or later. -See file `INSTALL' for compilation and installation instructions. -See file `ABOUT-NLS' for how to customize this program to your language. -See file `NEWS' for a list of major changes in the current release. -See file `AUTHORS' for the names of maintainers. -See file `THANKS' for a list of contributors. - -By using `./configure --with-gmp, you get multiple precision integral -and rational arithmetic using mpeval. The implementation depends on the -GNU gmp v2 library. - -By using `./configure --with-modules=`foo bar baz', you get an m4 with only -the named modules preloaded. The default modules (preloaded if you do not -use this option) are sufficient to do the job of GNU m4-1.4. Additional -modules may be desirable, or necessary if libltdl does not support your -host architecture. The implementation uses libltdl interface, details of -which are in the libtool manual. See file `modules/README' for a more -detailed description. - -By default, the `syscmd' and `esyscmd' macros try to use the first -instance of `sh' found by `command -p getconf PATH' at configure time, -with a default of `/bin/sh'. If that default is inappropriate, you -can use `./configure --with-syscmd-shell=location' to specify the -shell to use. - -By using `./configure --with-dmalloc', GNU m4 is linked with Gray -Watson's dmalloc package. It is a debugging option for finding memory -management problems. Gray Watson's dmalloc package is available at -ftp://ftp.letters.com/src/dmalloc/dmalloc.tar.gz. - -GNU M4 uses GNU Libtool in order to build shared libraries on a -variety of systems. While this is very nice for making usable -binaries, it can be a pain when trying to debug a program. For that -reason, compilation of shared libraries can be turned off by -specifying the `--disable-shared' option to `configure'. However, -without shared libraries, modules that are not preloaded will not be -available for use. - -Send bug reports, comments or ideas to `bug-m4@gnu.org'. A bug report -is an adequate description of the problem: your input, what you -expected, what you got, and why this is wrong. Diffs are welcome, but -they only describe a solution, from which the problem might be uneasy to -infer. Don't forget all relevant information about your operating -system, compiler, libraries, ... - -The easiest way to remember this information is by using the -testsuite. Any test failures are automatically logged, along with -lots of useful information about your setup; simply mailing -tests/testsuite.log to `bug-m4@gnu.org' is a good start. If you want -to dive in and debug a failure, you may find it useful to fine-tune -the execution of the testsuite. For example, running test 12 in -verbose mode can be done with: - -make check TESTSUITEFLAGS='-v -d -x 12' - -The testsuite understands --help to tell you more about the current -set of tests. +This repository has several branches. The one you have checked out +does not have any code. Instead, you will want to check out one of: +- branch-1.4: Latest stable release, most up-to-date +- branch-1.6: Some improvements to 1.4, but not yet finalized and released +- branch-2.0: Many new experimental features, hasn't been worked on in years For any copyright year range specified as YYYY-ZZZZ in this package -note that the range specifies every single year in that closed interval. +note that the range includes years in that closed interval; a more +precise determination of copyrightable changes can be obtained from +inspecting version control logs. ======================================================================== -Copyright (C) 2000, 2005-2011, 2013-2014, 2017 Free Software Foundation, -Inc. +Copyright (C) 2000-2021 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or diff --git a/TODO b/TODO deleted file mode 100644 index 9833f034..00000000 --- a/TODO +++ /dev/null @@ -1,150 +0,0 @@ -GNU m4 TODO - Tasks that need implementing. -*- outline -*- -Copyright (C) 2000-2001, 2006-2008, 2010, 2013-2014, 2017 Free Software -Foundation, Inc. - -Tell the maintainers at if you feel like volunteering -for any of these ideas or if you have others to add. - -* KNOWN BUGS - - + The following patch needs to be ported from the branch: - http://lists.gnu.org/archive/html/m4-patches/2007-03/msg00005.html - May be a couple of issues in that thread. - - + The format builtin needs more power to be like printf(1): - http://lists.gnu.org/archive/html/m4-discuss/2007-05/msg00015.html - But be aware of compatibility issues in making too many changes. - - + The test case `other-tests/stackovf.test' does not work. - - + stack overflow is basically broken - - The routines to detect stack overflow throuh segv are basically - broken. The idea may be fine, but it ends up calling a sigv handler - that uses gettext, printf, stdout... all of which are definitely NOT - sig-safe. Pity, because the hardcode routine is basically very careful - to use write(2), to avoid this. - - I haven't checked that translation magic is signal-safe. - - I doubt it; - - stdio is not signal-safe in any kind of portable setting anyways. - -- - Marc Espie - espie@schutzenberger.liafa.jussieu.fr - - Perhaps the gnulib c-stack module or libsigsegv would be useful: - http://lists.gnu.org/archive/html/bug-gnu-utils/2008-01/msg00042.html - -* FEATURES OR PROBLEMS - - + m4 should keep an ``execution stack'' of macros, which applications could - use in their error messages. - - + Implement discarding comment delimiters with the syntax table. - - + Implement qindir. Like indir, except that the result of the macro call - is not expanded. Because the input stack might contain a file or a - string, it is probably best achieved by making note that the TOS input - should be copied rather than rescanned. - - $ echo "a'b" > f - $ m4 - define(a,z)dnl - include(f)dnl - z'b - indir(`include', f)dnl - z'b - qindir(`include', f)dnl - a'b - define(b,NONO)dnl - patsubst(qindir(`include', f), `b', x) - z'x - - + Use the TOS input quoting for qindir to fix this undesirable POSIX - behavior: - - define(`x', -'-) - define(y, defn(`x')) - y - --' - -- - Stepan Kasal - - + If configured --with-gmp for multiple precision arithmetic there are - some warnings, but it passes the tests. - - + Make m4 show include dependencies like gcc so Makefile targets are - updated when their (included) input files are updated (Erick B). - - + Add support for wide character sets. - - -* OPTIMIZATION AND CLEAN UP - - + Have NULs go really undisturbed through GNU m4 - GNU m4 is lousy regarding NULs in streams (this would require - maintaining the string lengths, and avoiding strlen, strcpy, - etc.). (Almost there, once argv_ref is ported). - - + The argument count limits are handled for all tokens passed around by - the internals: we should enable attaching these values to text macros - too. - - + The context parameter is just a placeholder for formerly global state. - We should be making the library reentrant so that multiple instances - of m4 can be run in the same process at the same time. - - + The path management stuff (in path.c/m4private.h) is reinventing the - wheel. There are a bunch of fast path management and search functions - in ltdl.c: These need to be sanitized, exported through ltdl.h, and - then wrapped by the m4module.h path api. path.c can probably be removed - entirely at that point. - -* MODULE SPECIFIC ISSUES - - + Some way of linking a module statically is needed, for systems - without support for dynamic loading. - - + Some sort of module interface versioning system needs to be implemented - in the module loader and the freezer so that m4 can tell if it is being - asked to load a frozen file that requires versions of modules with - interface versions unsupported by the current release. - - + The module API should probably use functions, not data exports: - http://lists.gnu.org/archive/html/m4-patches/2007-09/msg00012.html - Actually, there are several good ideas for module in that thread. - - + Setting of the module search path within m4 scripts: - - append(__modulepath__, `/some/modules/live/here') - - + Module autoloader. This would allow an m4 core with no builtins except - for loadmodule(). A default startup script would mark the recognised - set of builtins for autoload from the installed module directory on first - use. A new cli parameter would inhibit initialisation from this script, - so that customised m4 interpreters could be built on the fly! - - + The module loader needs to differentiate between modules that are in - memory and modules that are loaded (i.e. visible) from various context - structures. - - + The perl module should only be built if a suitable perl interpreter - is found on the build machine. For that matter, it has been a - while since the perl module has even been built, and perl has had - new releases in the meantime. - - -Local Variables: -mode: outline -outline-regexp: " *[-+*.] \\| " -End: - -Copyright (C) 2000, 2006, 2007, 2009, 2010 Free Software Foundation, -Inc. - -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.3 or -any later version published by the Free Software Foundation; with no -Invariant Sections, with no Front-Cover Texts, and with no Back-Cover -Texts. A copy of the license is included in the ``GNU Free -Documentation License'' file as part of this distribution. diff --git a/bootstrap b/bootstrap deleted file mode 100755 index 8984cfd9..00000000 --- a/bootstrap +++ /dev/null @@ -1,5100 +0,0 @@ -#! /bin/sh -## DO NOT EDIT - This file generated from build-aux/bootstrap.in -## by inline-source v2014-01-03.01 - -# Bootstrap an Autotooled package from checked-out sources. -# Written by Gary V. Vaughan, 2010 - -# Copyright (C) 2010-2014, 2017 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Originally written by Paul Eggert. The canonical version of this -# script is maintained as build-aux/bootstrap in gnulib, however, to -# be useful to your project, you should place a copy of it under -# version control in the top-level directory of your project. The -# intent is that all customization can be done with a bootstrap.conf -# file also maintained in your version control; gnulib comes with a -# template build-aux/bootstrap.conf to get you started. - -# Please report bugs or propose patches to bug-gnulib@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# Most GNUish projects do not keep all of the generated Autotool -# files under version control, but running all of the right tools -# with the right arguments, in the correct order to regenerate -# all of those files in readiness for configuration and building -# can be surprisingly involved! Many projects have a 'bootstrap' -# script under version control to invoke Autotools and perform -# other assorted book-keeping with version numbers and the like. -# -# This bootstrap script aims to probe the configure.ac and top -# Makefile.am of your project to automatically determine what -# the correct ordering and arguments are and then run the tools for -# you. In order to use it, you can generate an initial standalone -# script with: -# -# gl/build-aux/inline-source gl/build-aux/bootstrap.in > bootstrap -# -# You should then store than script in version control for other -# developers in you project. It will give you instructions about -# how to keep it up to date if the sources change. -# -# See gl/doc/bootstrap.texi for documentation on how to write -# a bootstrap.conf to customize it for your project's -# idiosyncracies. - - -## ================================================================== ## -## ## -## DO NOT EDIT THIS FILE, CUSTOMIZE IT USING A BOOTSTRAP.CONF ## -## ## -## ================================================================== ## - -## ------------------------------- ## -## User overridable command paths. ## -## ------------------------------- ## - -# All uppercase denotes values stored in the environment. These -# variables should generally be overridden by the user - however, we do -# set them to 'true' in some parts of this script to prevent them being -# called at the wrong time by other tools that we call ('autoreconf', -# for example). -# -# We also allow 'LIBTOOLIZE', 'M4', 'SHA1SUM' and some others to be -# overridden, and export the result for child processes, but they are -# handled by the function 'func_find_tool' and not defaulted in this -# section. - -: ${ACLOCAL="aclocal"} -: ${AUTOCONF="autoconf"} -: ${AUTOHEADER="autoheader"} -: ${AUTOM4TE="autom4te"} -: ${AUTOHEADER="autoheader"} -: ${AUTOMAKE="automake"} -: ${AUTOPOINT="autopoint"} -: ${AUTORECONF="autoreconf"} -: ${CMP="cmp"} -: ${CONFIG_SHELL="/bin/sh"} -: ${DIFF="diff"} -: ${GIT="git"} -: ${LN_S="ln -s"} -: ${RM="rm"} - -export ACLOCAL -export AUTOCONF -export AUTOHEADER -export AUTOM4TE -export AUTOHEADER -export AUTOMAKE -export AUTOPOINT -export AUTORECONF -export CONFIG_SHELL - - -## -------------- ## -## Configuration. ## -## -------------- ## - -# A newline delimited list of triples of programs (that respond to -# --version), the minimum version numbers required (or just '-' in the -# version field if any version will be sufficient) and homepage URLs -# to help locate missing packages. -buildreq= - -# Name of a file containing instructions on installing missing packages -# required in 'buildreq'. -buildreq_readme=README-hacking - -# These are extracted from AC_INIT in configure.ac, though you can -# override those values in 'bootstrap.conf' if you prefer. -build_aux= -macro_dir= -package= -package_name= -package_version= -package_bugreport= - -# These are extracted from 'gnulib-cache.m4', or else fall-back -# automatically on the gnulib defaults; unless you set the values -# manually in 'bootstrap.conf'. -doc_base= -gnulib_mk= -gnulib_name= -local_gl_dir= -source_base= -tests_base= - -# The list of gnulib modules required at 'gnulib-tool' time. If you -# check 'gnulib-cache.m4' into your repository, then this list will be -# extracted automatically. -gnulib_modules= - -# Extra gnulib files that are not in modules, which override files of -# the same name installed by other bootstrap tools. -gnulib_non_module_files=" - build-aux/compile - build-aux/install-sh - build-aux/mdate-sh - build-aux/texinfo.tex - build-aux/depcomp - build-aux/config.guess - build-aux/config.sub - doc/INSTALL -" - -# Relative path to the local gnulib submodule, and url to the upstream -# git repository. If you have a gnulib entry in your .gitmodules file, -# these values are ignored. -gnulib_path= -gnulib_url= - -# Additional gnulib-tool options to use. -gnulib_tool_options=" - --no-changelog -" - -# bootstrap removes any macro-files that are not included by aclocal.m4, -# except for files listed in this variable that are always kept. -gnulib_precious=" - gnulib-tool.m4 -" - -# When truncating long commands for display, always allow at least this -# many characters before truncating. -min_cmd_len=160 - -# The command to download all .po files for a specified domain into -# a specified directory. Fill in the first %s is the domain name, and -# the second with the destination directory. Use rsync's -L and -r -# options because the latest/%s directory and the .po files within are -# all symlinks. -po_download_command_format=\ -"rsync --delete --exclude '*.s1' -Lrtvz \ -'translationproject.org::tp/latest/%s/' '%s'" - -# Other locale categories that need message catalogs. -extra_locale_categories= - -# Additional xgettext options to use. Gnulib might provide you with an -# extensive list of additional options to append to this, but gettext -# 0.16.1 and newer appends them automaticaly, so you can safely ignore -# the complaints from 'gnulib-tool' if your $configure_ac states: -# -# AM_GNU_GETTEXT_VERSION([0.16.1]) -xgettext_options=" - --flag=_:1:pass-c-format - --flag=N_:1:pass-c-format -" - -# Package copyright holder for gettext files. Defaults to FSF if unset. -copyright_holder= - -# File that should exist in the top directory of a checked out hierarchy, -# but not in a distribution tarball. -checkout_only_file= - -# Whether to use copies instead of symlinks by default (if set to true, -# the --copy option has no effect). -copy=false - -# Set this to ".cvsignore .gitignore" in 'bootstrap.conf' if you want -# those files to be generated in directories like 'lib/', 'm4/', and 'po/', -# or set it to "auto" to make this script select what to use based -# on what version control system (if any) is used in the source directory. -# Or set it to "none" to ignore VCS ignore files entirely. Default is -# "auto". -vc_ignore= - - -## ------------------- ## -## External Libraries. ## -## ------------------- ## - -# Source required external libraries: -# Set a version string for this script. -scriptversion=2014-01-03.01; # UTC - -# General shell script boiler plate, and helper functions. -# Written by Gary V. Vaughan, 2004 - -# Copyright (C) 2004-2014, 2017 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. - -# As a special exception to the GNU General Public License, if you distribute -# this file as part of a program or library that is built using GNU Libtool, -# you may include this file under the same distribution terms that you use -# for the rest of that program. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNES 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 . - -# Please report bugs or propose patches to gary@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# Evaluate this file near the top of your script to gain access to -# the functions and variables defined here: -# -# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh -# -# If you need to override any of the default environment variable -# settings, do that before evaluating this file. - - -## -------------------- ## -## Shell normalisation. ## -## -------------------- ## - -# Some shells need a little help to be as Bourne compatible as possible. -# Before doing anything else, make sure all that help has been provided! - -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac -fi - -# NLS nuisances: We save the old values in case they are required later. -_G_user_locale= -_G_safe_locale= -for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES -do - eval "if test set = \"\${$_G_var+set}\"; then - save_$_G_var=\$$_G_var - $_G_var=C - export $_G_var - _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" - _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" - fi" -done - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# Make sure IFS has a sensible default -sp=' ' -nl=' -' -IFS="$sp $nl" - -# There are apparently some retarded systems that use ';' as a PATH separator! -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - - -## ------------------------- ## -## Locate command utilities. ## -## ------------------------- ## - - -# func_executable_p FILE -# ---------------------- -# Check that FILE is an executable regular file. -func_executable_p () -{ - test -f "$1" && test -x "$1" -} - - -# func_path_progs PROGS_LIST CHECK_FUNC [PATH] -# -------------------------------------------- -# Search for either a program that responds to --version with output -# containing "GNU", or else returned by CHECK_FUNC otherwise, by -# trying all the directories in PATH with each of the elements of -# PROGS_LIST. -# -# CHECK_FUNC should accept the path to a candidate program, and -# set $func_check_prog_result if it truncates its output less than -# $_G_path_prog_max characters. -func_path_progs () -{ - _G_progs_list=$1 - _G_check_func=$2 - _G_PATH=${3-"$PATH"} - - _G_path_prog_max=0 - _G_path_prog_found=false - _G_save_IFS=$IFS; IFS=$PATH_SEPARATOR - for _G_dir in $_G_PATH; do - IFS=$_G_save_IFS - test -z "$_G_dir" && _G_dir=. - for _G_prog_name in $_G_progs_list; do - for _exeext in '' .EXE; do - _G_path_prog=$_G_dir/$_G_prog_name$_exeext - func_executable_p "$_G_path_prog" || continue - case `"$_G_path_prog" --version 2>&1` in - *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; - *) $_G_check_func $_G_path_prog - func_path_progs_result=$func_check_prog_result - ;; - esac - $_G_path_prog_found && break 3 - done - done - done - IFS=$_G_save_IFS - test -z "$func_path_progs_result" && { - echo "no acceptable sed could be found in \$PATH" >&2 - exit 1 - } -} - - -# We want to be able to use the functions in this file before configure -# has figured out where the best binaries are kept, which means we have -# to search for them ourselves - except when the results are already set -# where we skip the searches. - -# Unless the user overrides by setting SED, search the path for either GNU -# sed, or the sed that truncates its output the least. -test -z "$SED" && { - _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ - for _G_i in 1 2 3 4 5 6 7; do - _G_sed_script=$_G_sed_script$nl$_G_sed_script - done - echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed - _G_sed_script= - - func_check_prog_sed () - { - _G_path_prog=$1 - - _G_count=0 - printf 0123456789 >conftest.in - while : - do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo '' >> conftest.nl - "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break - diff conftest.out conftest.nl >/dev/null 2>&1 || break - _G_count=`expr $_G_count + 1` - if test "$_G_count" -gt "$_G_path_prog_max"; then - # Best one so far, save it but keep looking for a better one - func_check_prog_result=$_G_path_prog - _G_path_prog_max=$_G_count - fi - # 10*(2^10) chars as input seems more than enough - test 10 -lt "$_G_count" && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out - } - - func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin - rm -f conftest.sed - SED=$func_path_progs_result -} - - -# Unless the user overrides by setting GREP, search the path for either GNU -# grep, or the grep that truncates its output the least. -test -z "$GREP" && { - func_check_prog_grep () - { - _G_path_prog=$1 - - _G_count=0 - _G_path_prog_max=0 - printf 0123456789 >conftest.in - while : - do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo 'GREP' >> conftest.nl - "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break - diff conftest.out conftest.nl >/dev/null 2>&1 || break - _G_count=`expr $_G_count + 1` - if test "$_G_count" -gt "$_G_path_prog_max"; then - # Best one so far, save it but keep looking for a better one - func_check_prog_result=$_G_path_prog - _G_path_prog_max=$_G_count - fi - # 10*(2^10) chars as input seems more than enough - test 10 -lt "$_G_count" && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out - } - - func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin - GREP=$func_path_progs_result -} - - -## ------------------------------- ## -## User overridable command paths. ## -## ------------------------------- ## - -# All uppercase variable names are used for environment variables. These -# variables can be overridden by the user before calling a script that -# uses them if a suitable command of that name is not already available -# in the command search PATH. - -: ${CP="cp -f"} -: ${ECHO="printf %s\n"} -: ${EGREP="$GREP -E"} -: ${FGREP="$GREP -F"} -: ${LN_S="ln -s"} -: ${MAKE="make"} -: ${MKDIR="mkdir"} -: ${MV="mv -f"} -: ${RM="rm -f"} -: ${SHELL="${CONFIG_SHELL-/bin/sh}"} - - -## -------------------- ## -## Useful sed snippets. ## -## -------------------- ## - -sed_dirname='s|/[^/]*$||' -sed_basename='s|^.*/||' - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s|\([`"$\\]\)|\\\1|g' - -# Same as above, but do not quote variable references. -sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution that turns a string into a regex matching for the -# string literally. -sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' - -# Sed substitution that converts a w32 file name or path -# that contains forward slashes, into one that contains -# (escaped) backslashes. A very naive implementation. -sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' - -# Re-'\' parameter expansions in output of sed_double_quote_subst that -# were '\'-ed in input to the same. If an odd number of '\' preceded a -# '$' in input to sed_double_quote_subst, that '$' was protected from -# expansion. Since each input '\' is now two '\'s, look for any number -# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. -_G_bs='\\' -_G_bs2='\\\\' -_G_bs4='\\\\\\\\' -_G_dollar='\$' -sed_double_backslash="\ - s/$_G_bs4/&\\ -/g - s/^$_G_bs2$_G_dollar/$_G_bs&/ - s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g - s/\n//g" - - -## ----------------- ## -## Global variables. ## -## ----------------- ## - -# Except for the global variables explicitly listed below, the following -# functions in the '^func_' namespace, and the '^require_' namespace -# variables initialised in the 'Resource management' section, sourcing -# this file will not pollute your global namespace with anything -# else. There's no portable way to scope variables in Bourne shell -# though, so actually running these functions will sometimes place -# results into a variable named after the function, and often use -# temporary variables in the '^_G_' namespace. If you are careful to -# avoid using those namespaces casually in your sourcing script, things -# should continue to work as you expect. And, of course, you can freely -# overwrite any of the functions or variables defined here before -# calling anything to customize them. - -EXIT_SUCCESS=0 -EXIT_FAILURE=1 -EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. -EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. - -# Allow overriding, eg assuming that you follow the convention of -# putting '$debug_cmd' at the start of all your functions, you can get -# bash to show function call trace with: -# -# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name -debug_cmd=${debug_cmd-":"} -exit_cmd=: - -# By convention, finish your script with: -# -# exit $exit_status -# -# so that you can set exit_status to non-zero if you want to indicate -# something went wrong during execution without actually bailing out at -# the point of failure. -exit_status=$EXIT_SUCCESS - -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath=$0 - -# The name of this program. -progname=`$ECHO "$progpath" |$SED "$sed_basename"` - -# Make sure we have an absolute progpath for reexecution: -case $progpath in - [\\/]*|[A-Za-z]:\\*) ;; - *[\\/]*) - progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` - progdir=`cd "$progdir" && pwd` - progpath=$progdir/$progname - ;; - *) - _G_IFS=$IFS - IFS=${PATH_SEPARATOR-:} - for progdir in $PATH; do - IFS=$_G_IFS - test -x "$progdir/$progname" && break - done - IFS=$_G_IFS - test -n "$progdir" || progdir=`pwd` - progpath=$progdir/$progname - ;; -esac - - -## ----------------- ## -## Standard options. ## -## ----------------- ## - -# The following options affect the operation of the functions defined -# below, and should be set appropriately depending on run-time para- -# meters passed on the command line. - -opt_dry_run=false -opt_quiet=false -opt_verbose=false - -# Categories 'all' and 'none' are always available. Append any others -# you will pass as the first argument to func_warning from your own -# code. -warning_categories= - -# By default, display warnings according to 'opt_warning_types'. Set -# 'warning_func' to ':' to elide all warnings, or func_fatal_error to -# treat the next displayed warning as a fatal error. -warning_func=func_warn_and_continue - -# Set to 'all' to display all warnings, 'none' to suppress all -# warnings, or a space delimited list of some subset of -# 'warning_categories' to display only the listed warnings. -opt_warning_types=all - - -## -------------------- ## -## Resource management. ## -## -------------------- ## - -# This section contains definitions for functions that each ensure a -# particular resource (a file, or a non-empty configuration variable for -# example) is available, and if appropriate to extract default values -# from pertinent package files. Call them using their associated -# 'require_*' variable to ensure that they are executed, at most, once. -# -# It's entirely deliberate that calling these functions can set -# variables that don't obey the namespace limitations obeyed by the rest -# of this file, in order that that they be as useful as possible to -# callers. - - -# require_term_colors -# ------------------- -# Allow display of bold text on terminals that support it. -require_term_colors=func_require_term_colors -func_require_term_colors () -{ - $debug_cmd - - test -t 1 && { - # COLORTERM and USE_ANSI_COLORS environment variables take - # precedence, because most terminfo databases neglect to describe - # whether color sequences are supported. - test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} - - if test 1 = "$USE_ANSI_COLORS"; then - # Standard ANSI escape sequences - tc_reset='' - tc_bold=''; tc_standout='' - tc_red=''; tc_green='' - tc_blue=''; tc_cyan='' - else - # Otherwise trust the terminfo database after all. - test -n "`tput sgr0 2>/dev/null`" && { - tc_reset=`tput sgr0` - test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` - tc_standout=$tc_bold - test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` - test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` - test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` - test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` - test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` - } - fi - } - - require_term_colors=: -} - - -## ----------------- ## -## Function library. ## -## ----------------- ## - -# This section contains a variety of useful functions to call in your -# scripts. Take note of the portable wrappers for features provided by -# some modern shells, which will fall back to slower equivalents on -# less featureful shells. - - -# func_append VAR VALUE -# --------------------- -# Append VALUE onto the existing contents of VAR. - - # We should try to minimise forks, especially on Windows where they are - # unreasonably slow, so skip the feature probes when bash or zsh are - # being used: - if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then - : ${_G_HAVE_ARITH_OP="yes"} - : ${_G_HAVE_XSI_OPS="yes"} - # The += operator was introduced in bash 3.1 - case $BASH_VERSION in - [12].* | 3.0 | 3.0*) ;; - *) - : ${_G_HAVE_PLUSEQ_OP="yes"} - ;; - esac - fi - - # _G_HAVE_PLUSEQ_OP - # Can be empty, in which case the shell is probed, "yes" if += is - # useable or anything else if it does not work. - test -z "$_G_HAVE_PLUSEQ_OP" \ - && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ - && _G_HAVE_PLUSEQ_OP=yes - -if test yes = "$_G_HAVE_PLUSEQ_OP" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_append () - { - $debug_cmd - - eval "$1+=\$2" - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_append () - { - $debug_cmd - - eval "$1=\$$1\$2" - } -fi - - -# func_append_quoted VAR VALUE -# ---------------------------- -# Quote VALUE and append to the end of shell variable VAR, separated -# by a space. -if test yes = "$_G_HAVE_PLUSEQ_OP"; then - eval 'func_append_quoted () - { - $debug_cmd - - func_quote_for_eval "$2" - eval "$1+=\\ \$func_quote_for_eval_result" - }' -else - func_append_quoted () - { - $debug_cmd - - func_quote_for_eval "$2" - eval "$1=\$$1\\ \$func_quote_for_eval_result" - } -fi - - -# func_append_uniq VAR VALUE -# -------------------------- -# Append unique VALUE onto the existing contents of VAR, assuming -# entries are delimited by the first character of VALUE. For example: -# -# func_append_uniq options " --another-option option-argument" -# -# will only append to $options if " --another-option option-argument " -# is not already present somewhere in $options already (note spaces at -# each end implied by leading space in second argument). -func_append_uniq () -{ - $debug_cmd - - eval _G_current_value='`$ECHO $'$1'`' - _G_delim=`expr "$2" : '\(.\)'` - - case $_G_delim$_G_current_value$_G_delim in - *"$2$_G_delim"*) ;; - *) func_append "$@" ;; - esac -} - - -# func_arith TERM... -# ------------------ -# Set func_arith_result to the result of evaluating TERMs. - test -z "$_G_HAVE_ARITH_OP" \ - && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ - && _G_HAVE_ARITH_OP=yes - -if test yes = "$_G_HAVE_ARITH_OP"; then - eval 'func_arith () - { - $debug_cmd - - func_arith_result=$(( $* )) - }' -else - func_arith () - { - $debug_cmd - - func_arith_result=`expr "$@"` - } -fi - - -# func_basename FILE -# ------------------ -# Set func_basename_result to FILE with everything up to and including -# the last / stripped. -if test yes = "$_G_HAVE_XSI_OPS"; then - # If this shell supports suffix pattern removal, then use it to avoid - # forking. Hide the definitions single quotes in case the shell chokes - # on unsupported syntax... - _b='func_basename_result=${1##*/}' - _d='case $1 in - */*) func_dirname_result=${1%/*}$2 ;; - * ) func_dirname_result=$3 ;; - esac' - -else - # ...otherwise fall back to using sed. - _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' - _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` - if test "X$func_dirname_result" = "X$1"; then - func_dirname_result=$3 - else - func_append func_dirname_result "$2" - fi' -fi - -eval 'func_basename () -{ - $debug_cmd - - '"$_b"' -}' - - -# func_dirname FILE APPEND NONDIR_REPLACEMENT -# ------------------------------------------- -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -eval 'func_dirname () -{ - $debug_cmd - - '"$_d"' -}' - - -# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT -# -------------------------------------------------------- -# Perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# For efficiency, we do not delegate to the functions above but instead -# duplicate the functionality here. -eval 'func_dirname_and_basename () -{ - $debug_cmd - - '"$_b"' - '"$_d"' -}' - - -# func_echo ARG... -# ---------------- -# Echo program name prefixed message. -func_echo () -{ - $debug_cmd - - _G_message=$* - - func_echo_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_IFS - $ECHO "$progname: $_G_line" - done - IFS=$func_echo_IFS -} - - -# func_echo_all ARG... -# -------------------- -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} - - -# func_echo_infix_1 INFIX ARG... -# ------------------------------ -# Echo program name, followed by INFIX on the first line, with any -# additional lines not showing INFIX. -func_echo_infix_1 () -{ - $debug_cmd - - $require_term_colors - - _G_infix=$1; shift - _G_indent=$_G_infix - _G_prefix="$progname: $_G_infix: " - _G_message=$* - - # Strip color escape sequences before counting printable length - for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" - do - test -n "$_G_tc" && { - _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` - _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` - } - done - _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes - - func_echo_infix_1_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_infix_1_IFS - $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 - _G_prefix=$_G_indent - done - IFS=$func_echo_infix_1_IFS -} - - -# func_error ARG... -# ----------------- -# Echo program name prefixed message to standard error. -func_error () -{ - $debug_cmd - - $require_term_colors - - func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 -} - - -# func_fatal_error ARG... -# ----------------------- -# Echo program name prefixed message to standard error, and exit. -func_fatal_error () -{ - $debug_cmd - - func_error "$*" - exit $EXIT_FAILURE -} - - -# func_grep EXPRESSION FILENAME -# ----------------------------- -# Check whether EXPRESSION matches any line of FILENAME, without output. -func_grep () -{ - $debug_cmd - - $GREP "$1" "$2" >/dev/null 2>&1 -} - - -# func_len STRING -# --------------- -# Set func_len_result to the length of STRING. STRING may not -# start with a hyphen. - test -z "$_G_HAVE_XSI_OPS" \ - && (eval 'x=a/b/c; - test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ - && _G_HAVE_XSI_OPS=yes - -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_len () - { - $debug_cmd - - func_len_result=${#1} - }' -else - func_len () - { - $debug_cmd - - func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` - } -fi - - -# func_mkdir_p DIRECTORY-PATH -# --------------------------- -# Make sure the entire path to DIRECTORY-PATH is available. -func_mkdir_p () -{ - $debug_cmd - - _G_directory_path=$1 - _G_dir_list= - - if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then - - # Protect directory names starting with '-' - case $_G_directory_path in - -*) _G_directory_path=./$_G_directory_path ;; - esac - - # While some portion of DIR does not yet exist... - while test ! -d "$_G_directory_path"; do - # ...make a list in topmost first order. Use a colon delimited - # list incase some portion of path contains whitespace. - _G_dir_list=$_G_directory_path:$_G_dir_list - - # If the last portion added has no slash in it, the list is done - case $_G_directory_path in */*) ;; *) break ;; esac - - # ...otherwise throw away the child directory and loop - _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` - done - _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` - - func_mkdir_p_IFS=$IFS; IFS=: - for _G_dir in $_G_dir_list; do - IFS=$func_mkdir_p_IFS - # mkdir can fail with a 'File exist' error if two processes - # try to create one of the directories concurrently. Don't - # stop in that case! - $MKDIR "$_G_dir" 2>/dev/null || : - done - IFS=$func_mkdir_p_IFS - - # Bail out if we (or some other process) failed to create a directory. - test -d "$_G_directory_path" || \ - func_fatal_error "Failed to create '$1'" - fi -} - - -# func_mktempdir [BASENAME] -# ------------------------- -# Make a temporary directory that won't clash with other running -# libtool processes, and avoids race conditions if possible. If -# given, BASENAME is the basename for that directory. -func_mktempdir () -{ - $debug_cmd - - _G_template=${TMPDIR-/tmp}/${1-$progname} - - if test : = "$opt_dry_run"; then - # Return a directory name, but don't create it in dry-run mode - _G_tmpdir=$_G_template-$$ - else - - # If mktemp works, use that first and foremost - _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` - - if test ! -d "$_G_tmpdir"; then - # Failing that, at least try and use $RANDOM to avoid a race - _G_tmpdir=$_G_template-${RANDOM-0}$$ - - func_mktempdir_umask=`umask` - umask 0077 - $MKDIR "$_G_tmpdir" - umask $func_mktempdir_umask - fi - - # If we're not in dry-run mode, bomb out on failure - test -d "$_G_tmpdir" || \ - func_fatal_error "cannot create temporary directory '$_G_tmpdir'" - fi - - $ECHO "$_G_tmpdir" -} - - -# func_normal_abspath PATH -# ------------------------ -# Remove doubled-up and trailing slashes, "." path components, -# and cancel out any ".." path components in PATH after making -# it an absolute path. -func_normal_abspath () -{ - $debug_cmd - - # These SED scripts presuppose an absolute path with a trailing slash. - _G_pathcar='s|^/\([^/]*\).*$|\1|' - _G_pathcdr='s|^/[^/]*||' - _G_removedotparts=':dotsl - s|/\./|/|g - t dotsl - s|/\.$|/|' - _G_collapseslashes='s|/\{1,\}|/|g' - _G_finalslash='s|/*$|/|' - - # Start from root dir and reassemble the path. - func_normal_abspath_result= - func_normal_abspath_tpath=$1 - func_normal_abspath_altnamespace= - case $func_normal_abspath_tpath in - "") - # Empty path, that just means $cwd. - func_stripname '' '/' "`pwd`" - func_normal_abspath_result=$func_stripname_result - return - ;; - # The next three entries are used to spot a run of precisely - # two leading slashes without using negated character classes; - # we take advantage of case's first-match behaviour. - ///*) - # Unusual form of absolute path, do nothing. - ;; - //*) - # Not necessarily an ordinary path; POSIX reserves leading '//' - # and for example Cygwin uses it to access remote file shares - # over CIFS/SMB, so we conserve a leading double slash if found. - func_normal_abspath_altnamespace=/ - ;; - /*) - # Absolute path, do nothing. - ;; - *) - # Relative path, prepend $cwd. - func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath - ;; - esac - - # Cancel out all the simple stuff to save iterations. We also want - # the path to end with a slash for ease of parsing, so make sure - # there is one (and only one) here. - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` - while :; do - # Processed it all yet? - if test / = "$func_normal_abspath_tpath"; then - # If we ascended to the root using ".." the result may be empty now. - if test -z "$func_normal_abspath_result"; then - func_normal_abspath_result=/ - fi - break - fi - func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_pathcar"` - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_pathcdr"` - # Figure out what to do with it - case $func_normal_abspath_tcomponent in - "") - # Trailing empty path component, ignore it. - ;; - ..) - # Parent dir; strip last assembled component from result. - func_dirname "$func_normal_abspath_result" - func_normal_abspath_result=$func_dirname_result - ;; - *) - # Actual path component, append it. - func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" - ;; - esac - done - # Restore leading double-slash if one was found on entry. - func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result -} - - -# func_notquiet ARG... -# -------------------- -# Echo program name prefixed message only when not in quiet mode. -func_notquiet () -{ - $debug_cmd - - $opt_quiet || func_echo ${1+"$@"} - - # A bug in bash halts the script if the last line of a function - # fails when set -e is in force, so we need another command to - # work around that: - : -} - - -# func_relative_path SRCDIR DSTDIR -# -------------------------------- -# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. -func_relative_path () -{ - $debug_cmd - - func_relative_path_result= - func_normal_abspath "$1" - func_relative_path_tlibdir=$func_normal_abspath_result - func_normal_abspath "$2" - func_relative_path_tbindir=$func_normal_abspath_result - - # Ascend the tree starting from libdir - while :; do - # check if we have found a prefix of bindir - case $func_relative_path_tbindir in - $func_relative_path_tlibdir) - # found an exact match - func_relative_path_tcancelled= - break - ;; - $func_relative_path_tlibdir*) - # found a matching prefix - func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" - func_relative_path_tcancelled=$func_stripname_result - if test -z "$func_relative_path_result"; then - func_relative_path_result=. - fi - break - ;; - *) - func_dirname $func_relative_path_tlibdir - func_relative_path_tlibdir=$func_dirname_result - if test -z "$func_relative_path_tlibdir"; then - # Have to descend all the way to the root! - func_relative_path_result=../$func_relative_path_result - func_relative_path_tcancelled=$func_relative_path_tbindir - break - fi - func_relative_path_result=../$func_relative_path_result - ;; - esac - done - - # Now calculate path; take care to avoid doubling-up slashes. - func_stripname '' '/' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - func_stripname '/' '/' "$func_relative_path_tcancelled" - if test -n "$func_stripname_result"; then - func_append func_relative_path_result "/$func_stripname_result" - fi - - # Normalisation. If bindir is libdir, return '.' else relative path. - if test -n "$func_relative_path_result"; then - func_stripname './' '' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - fi - - test -n "$func_relative_path_result" || func_relative_path_result=. - - : -} - - -# func_quote_for_eval ARG... -# -------------------------- -# Aesthetically quote ARGs to be evaled later. -# This function returns two values: -# i) func_quote_for_eval_result -# double-quoted, suitable for a subsequent eval -# ii) func_quote_for_eval_unquoted_result -# has all characters that are still active within double -# quotes backslashified. -func_quote_for_eval () -{ - $debug_cmd - - func_quote_for_eval_unquoted_result= - func_quote_for_eval_result= - while test 0 -lt $#; do - case $1 in - *[\\\`\"\$]*) - _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; - *) - _G_unquoted_arg=$1 ;; - esac - if test -n "$func_quote_for_eval_unquoted_result"; then - func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" - else - func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" - fi - - case $_G_unquoted_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and variable expansion - # for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - _G_quoted_arg=\"$_G_unquoted_arg\" - ;; - *) - _G_quoted_arg=$_G_unquoted_arg - ;; - esac - - if test -n "$func_quote_for_eval_result"; then - func_append func_quote_for_eval_result " $_G_quoted_arg" - else - func_append func_quote_for_eval_result "$_G_quoted_arg" - fi - shift - done -} - - -# func_quote_for_expand ARG -# ------------------------- -# Aesthetically quote ARG to be evaled later; same as above, -# but do not quote variable references. -func_quote_for_expand () -{ - $debug_cmd - - case $1 in - *[\\\`\"]*) - _G_arg=`$ECHO "$1" | $SED \ - -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; - *) - _G_arg=$1 ;; - esac - - case $_G_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting and command substitution for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - _G_arg=\"$_G_arg\" - ;; - esac - - func_quote_for_expand_result=$_G_arg -} - - -# func_stripname PREFIX SUFFIX NAME -# --------------------------------- -# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_stripname () - { - $debug_cmd - - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary variable first. - func_stripname_result=$3 - func_stripname_result=${func_stripname_result#"$1"} - func_stripname_result=${func_stripname_result%"$2"} - }' -else - func_stripname () - { - $debug_cmd - - case $2 in - .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; - *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; - esac - } -fi - - -# func_show_eval CMD [FAIL_EXP] -# ----------------------------- -# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () -{ - $debug_cmd - - _G_cmd=$1 - _G_fail_exp=${2-':'} - - func_quote_for_expand "$_G_cmd" - eval "func_notquiet $func_quote_for_expand_result" - - $opt_dry_run || { - eval "$_G_cmd" - _G_status=$? - if test 0 -ne "$_G_status"; then - eval "(exit $_G_status); $_G_fail_exp" - fi - } -} - - -# func_show_eval_locale CMD [FAIL_EXP] -# ------------------------------------ -# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. Use the saved locale for evaluation. -func_show_eval_locale () -{ - $debug_cmd - - _G_cmd=$1 - _G_fail_exp=${2-':'} - - $opt_quiet || { - func_quote_for_expand "$_G_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - $opt_dry_run || { - eval "$_G_user_locale - $_G_cmd" - _G_status=$? - eval "$_G_safe_locale" - if test 0 -ne "$_G_status"; then - eval "(exit $_G_status); $_G_fail_exp" - fi - } -} - - -# func_tr_sh -# ---------- -# Turn $1 into a string suitable for a shell variable name. -# Result is stored in $func_tr_sh_result. All characters -# not in the set a-zA-Z0-9_ are replaced with '_'. Further, -# if $1 begins with a digit, a '_' is prepended as well. -func_tr_sh () -{ - $debug_cmd - - case $1 in - [0-9]* | *[!a-zA-Z0-9_]*) - func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` - ;; - * ) - func_tr_sh_result=$1 - ;; - esac -} - - -# func_verbose ARG... -# ------------------- -# Echo program name prefixed message in verbose mode only. -func_verbose () -{ - $debug_cmd - - $opt_verbose && func_echo "$*" - - : -} - - -# func_warn_and_continue ARG... -# ----------------------------- -# Echo program name prefixed warning message to standard error. -func_warn_and_continue () -{ - $debug_cmd - - $require_term_colors - - func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 -} - - -# func_warning CATEGORY ARG... -# ---------------------------- -# Echo program name prefixed warning message to standard error. Warning -# messages can be filtered according to CATEGORY, where this function -# elides messages where CATEGORY is not listed in the global variable -# 'opt_warning_types'. -func_warning () -{ - $debug_cmd - - # CATEGORY must be in the warning_categories list! - case " $warning_categories " in - *" $1 "*) ;; - *) func_internal_error "invalid warning category '$1'" ;; - esac - - _G_category=$1 - shift - - case " $opt_warning_types " in - *" $_G_category "*) $warning_func ${1+"$@"} ;; - esac -} - - -# func_sort_ver VER1 VER2 -# ----------------------- -# 'sort -V' is not generally available. -# Note this deviates from the version comparison in automake -# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a -# but this should suffice as we won't be specifying old -# version formats or redundant trailing .0 in bootstrap.conf. -# If we did want full compatibility then we should probably -# use m4_version_compare from autoconf. -func_sort_ver () -{ - $debug_cmd - - printf '%s\n%s\n' "$1" "$2" \ - | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n -} - -# func_lt_ver PREV CURR -# --------------------- -# Return true if PREV and CURR are in the correct order according to -# func_sort_ver, otherwise false. Use it like this: -# -# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." -func_lt_ver () -{ - $debug_cmd - - test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` -} - - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: -#! /bin/sh - -# Set a version string for this script. -scriptversion=2014-01-07.03; # UTC - -# A portable, pluggable option parser for Bourne shell. -# Written by Gary V. Vaughan, 2010 - -# Copyright (C) 2010-2014, 2017 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Please report bugs or propose patches to gary@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# This file is a library for parsing options in your shell scripts along -# with assorted other useful supporting features that you can make use -# of too. -# -# For the simplest scripts you might need only: -# -# #!/bin/sh -# . relative/path/to/funclib.sh -# . relative/path/to/options-parser -# scriptversion=1.0 -# func_options ${1+"$@"} -# eval set dummy "$func_options_result"; shift -# ...rest of your script... -# -# In order for the '--version' option to work, you will need to have a -# suitably formatted comment like the one at the top of this file -# starting with '# Written by ' and ending with '# warranty; '. -# -# For '-h' and '--help' to work, you will also need a one line -# description of your script's purpose in a comment directly above the -# '# Written by ' line, like the one at the top of this file. -# -# The default options also support '--debug', which will turn on shell -# execution tracing (see the comment above debug_cmd below for another -# use), and '--verbose' and the func_verbose function to allow your script -# to display verbose messages only when your user has specified -# '--verbose'. -# -# After sourcing this file, you can plug processing for additional -# options by amending the variables from the 'Configuration' section -# below, and following the instructions in the 'Option parsing' -# section further down. - -## -------------- ## -## Configuration. ## -## -------------- ## - -# You should override these variables in your script after sourcing this -# file so that they reflect the customisations you have added to the -# option parser. - -# The usage line for option parsing errors and the start of '-h' and -# '--help' output messages. You can embed shell variables for delayed -# expansion at the time the message is displayed, but you will need to -# quote other shell meta-characters carefully to prevent them being -# expanded when the contents are evaled. -usage='$progpath [OPTION]...' - -# Short help message in response to '-h' and '--help'. Add to this or -# override it after sourcing this library to reflect the full set of -# options your script accepts. -usage_message="\ - --debug enable verbose shell tracing - -W, --warnings=CATEGORY - report the warnings falling in CATEGORY [all] - -v, --verbose verbosely report processing - --version print version information and exit - -h, --help print short or long help message and exit -" - -# Additional text appended to 'usage_message' in response to '--help'. -long_help_message=" -Warning categories include: - 'all' show all warnings - 'none' turn off all the warnings - 'error' warnings are treated as fatal errors" - -# Help message printed before fatal option parsing errors. -fatal_help="Try '\$progname --help' for more information." - - - -## ------------------------- ## -## Hook function management. ## -## ------------------------- ## - -# This section contains functions for adding, removing, and running hooks -# to the main code. A hook is just a named list of of function, that can -# be run in order later on. - -# func_hookable FUNC_NAME -# ----------------------- -# Declare that FUNC_NAME will run hooks added with -# 'func_add_hook FUNC_NAME ...'. -func_hookable () -{ - $debug_cmd - - func_append hookable_fns " $1" -} - - -# func_add_hook FUNC_NAME HOOK_FUNC -# --------------------------------- -# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must -# first have been declared "hookable" by a call to 'func_hookable'. -func_add_hook () -{ - $debug_cmd - - case " $hookable_fns " in - *" $1 "*) ;; - *) func_fatal_error "'$1' does not accept hook functions." ;; - esac - - eval func_append ${1}_hooks '" $2"' -} - - -# func_remove_hook FUNC_NAME HOOK_FUNC -# ------------------------------------ -# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. -func_remove_hook () -{ - $debug_cmd - - eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' -} - - -# func_run_hooks FUNC_NAME [ARG]... -# --------------------------------- -# Run all hook functions registered to FUNC_NAME. -# It is assumed that the list of hook functions contains nothing more -# than a whitespace-delimited list of legal shell function names, and -# no effort is wasted trying to catch shell meta-characters or preserve -# whitespace. -func_run_hooks () -{ - $debug_cmd - - case " $hookable_fns " in - *" $1 "*) ;; - *) func_fatal_error "'$1' does not support hook funcions.n" ;; - esac - - eval _G_hook_fns=\$$1_hooks; shift - - for _G_hook in $_G_hook_fns; do - eval $_G_hook '"$@"' - - # store returned options list back into positional - # parameters for next 'cmd' execution. - eval _G_hook_result=\$${_G_hook}_result - eval set dummy "$_G_hook_result"; shift - done - - func_quote_for_eval ${1+"$@"} - func_run_hooks_result=$func_quote_for_eval_result -} - - - -## --------------- ## -## Option parsing. ## -## --------------- ## - -# In order to add your own option parsing hooks, you must accept the -# full positional parameter list in your hook function, remove any -# options that you action, and then pass back the remaining unprocessed -# options in '_result', escaped suitably for -# 'eval'. Like this: -# -# my_options_prep () -# { -# $debug_cmd -# -# # Extend the existing usage message. -# usage_message=$usage_message' -# -s, --silent don'\''t print informational messages -# ' -# -# func_quote_for_eval ${1+"$@"} -# my_options_prep_result=$func_quote_for_eval_result -# } -# func_add_hook func_options_prep my_options_prep -# -# -# my_silent_option () -# { -# $debug_cmd -# -# # Note that for efficiency, we parse as many options as we can -# # recognise in a loop before passing the remainder back to the -# # caller on the first unrecognised argument we encounter. -# while test $# -gt 0; do -# opt=$1; shift -# case $opt in -# --silent|-s) opt_silent=: ;; -# # Separate non-argument short options: -# -s*) func_split_short_opt "$_G_opt" -# set dummy "$func_split_short_opt_name" \ -# "-$func_split_short_opt_arg" ${1+"$@"} -# shift -# ;; -# *) set dummy "$_G_opt" "$*"; shift; break ;; -# esac -# done -# -# func_quote_for_eval ${1+"$@"} -# my_silent_option_result=$func_quote_for_eval_result -# } -# func_add_hook func_parse_options my_silent_option -# -# -# my_option_validation () -# { -# $debug_cmd -# -# $opt_silent && $opt_verbose && func_fatal_help "\ -# '--silent' and '--verbose' options are mutually exclusive." -# -# func_quote_for_eval ${1+"$@"} -# my_option_validation_result=$func_quote_for_eval_result -# } -# func_add_hook func_validate_options my_option_validation -# -# You'll alse need to manually amend $usage_message to reflect the extra -# options you parse. It's preferable to append if you can, so that -# multiple option parsing hooks can be added safely. - - -# func_options [ARG]... -# --------------------- -# All the functions called inside func_options are hookable. See the -# individual implementations for details. -func_hookable func_options -func_options () -{ - $debug_cmd - - func_options_prep ${1+"$@"} - eval func_parse_options \ - ${func_options_prep_result+"$func_options_prep_result"} - eval func_validate_options \ - ${func_parse_options_result+"$func_parse_options_result"} - - eval func_run_hooks func_options \ - ${func_validate_options_result+"$func_validate_options_result"} - - # save modified positional parameters for caller - func_options_result=$func_run_hooks_result -} - - -# func_options_prep [ARG]... -# -------------------------- -# All initialisations required before starting the option parse loop. -# Note that when calling hook functions, we pass through the list of -# positional parameters. If a hook function modifies that list, and -# needs to propogate that back to rest of this script, then the complete -# modified list must be put in 'func_run_hooks_result' before -# returning. -func_hookable func_options_prep -func_options_prep () -{ - $debug_cmd - - # Option defaults: - opt_verbose=false - opt_warning_types= - - func_run_hooks func_options_prep ${1+"$@"} - - # save modified positional parameters for caller - func_options_prep_result=$func_run_hooks_result -} - - -# func_parse_options [ARG]... -# --------------------------- -# The main option parsing loop. -func_hookable func_parse_options -func_parse_options () -{ - $debug_cmd - - func_parse_options_result= - - # this just eases exit handling - while test $# -gt 0; do - # Defer to hook functions for initial option parsing, so they - # get priority in the event of reusing an option name. - func_run_hooks func_parse_options ${1+"$@"} - - # Adjust func_parse_options positional parameters to match - eval set dummy "$func_run_hooks_result"; shift - - # Break out of the loop if we already parsed every option. - test $# -gt 0 || break - - _G_opt=$1 - shift - case $_G_opt in - --debug|-x) debug_cmd='set -x' - func_echo "enabling shell trace mode" - $debug_cmd - ;; - - --no-warnings|--no-warning|--no-warn) - set dummy --warnings none ${1+"$@"} - shift - ;; - - --warnings|--warning|-W) - test $# = 0 && func_missing_arg $_G_opt && break - case " $warning_categories $1" in - *" $1 "*) - # trailing space prevents matching last $1 above - func_append_uniq opt_warning_types " $1" - ;; - *all) - opt_warning_types=$warning_categories - ;; - *none) - opt_warning_types=none - warning_func=: - ;; - *error) - opt_warning_types=$warning_categories - warning_func=func_fatal_error - ;; - *) - func_fatal_error \ - "unsupported warning category: '$1'" - ;; - esac - shift - ;; - - --verbose|-v) opt_verbose=: ;; - --version) func_version ;; - -\?|-h) func_usage ;; - --help) func_help ;; - - # Separate optargs to long options (plugins may need this): - --*=*) func_split_equals "$_G_opt" - set dummy "$func_split_equals_lhs" \ - "$func_split_equals_rhs" ${1+"$@"} - shift - ;; - - # Separate optargs to short options: - -W*) - func_split_short_opt "$_G_opt" - set dummy "$func_split_short_opt_name" \ - "$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - # Separate non-argument short options: - -\?*|-h*|-v*|-x*) - func_split_short_opt "$_G_opt" - set dummy "$func_split_short_opt_name" \ - "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - --) break ;; - -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; - *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; - esac - done - - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - func_parse_options_result=$func_quote_for_eval_result -} - - -# func_validate_options [ARG]... -# ------------------------------ -# Perform any sanity checks on option settings and/or unconsumed -# arguments. -func_hookable func_validate_options -func_validate_options () -{ - $debug_cmd - - # Display all warnings if -W was not given. - test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" - - func_run_hooks func_validate_options ${1+"$@"} - - # Bail if the options were screwed! - $exit_cmd $EXIT_FAILURE - - # save modified positional parameters for caller - func_validate_options_result=$func_run_hooks_result -} - - - -## ----------------- ## -## Helper functions. ## -## ----------------- ## - -# This section contains the helper functions used by the rest of the -# hookable option parser framework in ascii-betical order. - - -# func_fatal_help ARG... -# ---------------------- -# Echo program name prefixed message to standard error, followed by -# a help hint, and exit. -func_fatal_help () -{ - $debug_cmd - - eval \$ECHO \""Usage: $usage"\" - eval \$ECHO \""$fatal_help"\" - func_error ${1+"$@"} - exit $EXIT_FAILURE -} - - -# func_help -# --------- -# Echo long help message to standard output and exit. -func_help () -{ - $debug_cmd - - func_usage_message - $ECHO "$long_help_message" - exit 0 -} - - -# func_missing_arg ARGNAME -# ------------------------ -# Echo program name prefixed message to standard error and set global -# exit_cmd. -func_missing_arg () -{ - $debug_cmd - - func_error "Missing argument for '$1'." - exit_cmd=exit -} - - -# func_split_equals STRING -# ------------------------ -# Set func_split_equals_lhs and func_split_equals_rhs shell variables after -# splitting STRING at the '=' sign. -test -z "$_G_HAVE_XSI_OPS" \ - && (eval 'x=a/b/c; - test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ - && _G_HAVE_XSI_OPS=yes - -if test yes = "$_G_HAVE_XSI_OPS" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_split_equals () - { - $debug_cmd - - func_split_equals_lhs=${1%%=*} - func_split_equals_rhs=${1#*=} - test "x$func_split_equals_lhs" = "x$1" \ - && func_split_equals_rhs= - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_split_equals () - { - $debug_cmd - - func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` - func_split_equals_rhs= - test "x$func_split_equals_lhs" = "x$1" \ - || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` - } -fi #func_split_equals - - -# func_split_short_opt SHORTOPT -# ----------------------------- -# Set func_split_short_opt_name and func_split_short_opt_arg shell -# variables after splitting SHORTOPT after the 2nd character. -if test yes = "$_G_HAVE_XSI_OPS" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_split_short_opt () - { - $debug_cmd - - func_split_short_opt_arg=${1#??} - func_split_short_opt_name=${1%"$func_split_short_opt_arg"} - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_split_short_opt () - { - $debug_cmd - - func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` - func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` - } -fi #func_split_short_opt - - -# func_usage -# ---------- -# Echo short help message to standard output and exit. -func_usage () -{ - $debug_cmd - - func_usage_message - $ECHO "Run '$progname --help |${PAGER-more}' for full usage" - exit 0 -} - - -# func_usage_message -# ------------------ -# Echo short help message to standard output. -func_usage_message () -{ - $debug_cmd - - eval \$ECHO \""Usage: $usage"\" - echo - $SED -n 's|^# || - /^Written by/{ - x;p;x - } - h - /^Written by/q' < "$progpath" - echo - eval \$ECHO \""$usage_message"\" -} - - -# func_version -# ------------ -# Echo version message to standard output and exit. -func_version () -{ - $debug_cmd - - printf '%s\n' "$progname $scriptversion" - $SED -n ' - /(C)/!b go - :more - /\./!{ - N - s|\n# | | - b more - } - :go - /^# Written by /,/# warranty; / { - s|^# || - s|^# *$|| - s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| - p - } - /^# Written by / { - s|^# || - p - } - /^warranty; /q' < "$progpath" - - exit $? -} - - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: -#! /bin/sh - -# Extract macro arguments from autotools input with GNU M4. -# Written by Gary V. Vaughan, 2010 -# -# Copyright (C) 2010-2014, 2017 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# Make sure we've evaluated scripts we depend on. -test -z "$progpath" && . `echo "$0" |${SED-sed} 's|[^/]*$||'`/funclib.sh -test extract-trace = "$progname" && . `echo "$0" |${SED-sed} 's|[^/]*$||'`/options-parser - -# Set a version string. -scriptversion=2014-01-04.01; # UTC - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Please report bugs or propose patches to gary@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# Run './extract-trace --help' for help with using this script from the -# command line. -# -# Or source first 'options-parser' and then this file into your own -# scripts in order to make use of the function and variable framework -# they define, and also to avoid the overhead of forking to run this -# script in its own process on every call. - - - -## ----------------- ## -## Helper functions. ## -## ----------------- ## - -# This section contains the helper functions used by the rest of -# 'extract-trace'. - - -# func_autoconf_configure MAYBE-CONFIGURE-FILE -# -------------------------------------------- -# Ensure that MAYBE-CONFIGURE-FILE is the name of a file in the current -# directory that contains an uncommented call to AC_INIT. -func_autoconf_configure () -{ - $debug_cmd - - _G_sed_no_comment=' - s|#.*$|| - s|^dnl .*$|| - s| dnl .*$||' - _G_ac_init= - - # If we were passed a genuine file, make sure it calls AC_INIT. - test -f "$1" \ - && _G_ac_init=`$SED "$_G_sed_no_comment" "$1" |$GREP AC_INIT` - - # Otherwise it is not a genuine Autoconf input file. - test -n "$_G_ac_init" - _G_status=$? - - test 0 -ne "$_G_status" \ - && func_verbose "'$1' not using Autoconf" - - (exit $_G_status) -} - - -# func_find_tool ENVVAR NAMES... -# ------------------------------ -# Search for a required program. Use the value of ENVVAR, if set, -# otherwise find the first of the NAMES that can be run (i.e., -# supports --version). If found, set ENVVAR to the program name, -# die otherwise. -func_find_tool () -{ - $debug_cmd - - _G_find_tool_envvar=$1 - shift - _G_find_tool_names=$@ - eval "_G_find_tool_res=\$$_G_find_tool_envvar" - if test -n "$_G_find_tool_res"; then - _G_find_tool_error_prefix="\$$find_tool_envvar: " - else - for _G_prog - do - if func_tool_version_output $_G_prog >/dev/null; then - _G_find_tool_res=$_G_prog - break - fi - done - fi - if test -n "$_G_find_tool_res"; then - func_tool_version_output >/dev/null $_G_find_tool_res "\ -${_G_find_tool_error_prefix}Cannot run '$_G_find_tool_res --version'" - - # Make sure the result is exported to the environment for children - # to use. - eval "$_G_find_tool_envvar=\$_G_find_tool_res" - eval "export $_G_find_tool_envvar" - else - func_error "\ -One of these is required: - $_G_find_tool_names" - fi -} - - -# func_tool_version_output CMD [FATAL-ERROR-MSG] -# ---------------------------------------------- -# Attempt to run 'CMD --version', discarding errors. The output can be -# ignored by redirecting stdout, and this function used simply to test -# whether the command exists and exits normally when passed a -# '--version' argument. -# When FATAL-ERROR-MSG is given, then this function will display the -# message and exit if running 'CMD --version' returns a non-zero exit -# status. -func_tool_version_output () -{ - $debug_cmd - - _G_cmd=$1 - _G_fatal_error_msg=$2 - - # Some tools, like 'git2cl' produce thousands of lines of output - # unless stdin is /dev/null - in that case we want to return - # successfully without saving all of that output. Other tools, - # such as 'help2man' exit with a non-zero status when stdin comes - # from /dev/null, so we re-execute without /dev/null if that - # happens. This means that occasionally, the output from both calls - # ends up in the result, but the alternative would be to discard the - # output from one call, and hope the other produces something useful. - { $_G_cmd --version /dev/null - _G_status=$? - - test 0 -ne "$_G_status" && test -n "$_G_fatal_error_msg" \ - && func_fatal_error "$_G_fatal_error_msg" - - (exit $_G_status) -} - - -## -------------------- ## -## Resource management. ## -## -------------------- ## - -# This section contains definitions for functions that each ensure a -# particular resource (a file, or a non-empty configuration variable for -# example) is available, and if appropriate to extract default values -# from pertinent package files. Where a variable already has a non- -# empty value (as set by the package's 'bootstrap.conf'), that value is -# used in preference to deriving the default. Call them using their -# associated 'require_*' variable to ensure that they are executed, at -# most, once. -# -# It's entirely deliberate that calling these functions can set -# variables that don't obey the namespace limitations obeyed by the rest -# of this file, in order that that they be as useful as possible to -# callers. - - -# require_configure_ac -# -------------------- -# Ensure that there is a 'configure.ac' or 'configure.in' file in the -# current directory that contains an uncommented call to AC_INIT, and -# that '$configure_ac' contains its name. -require_configure_ac=func_require_configure_ac -func_require_configure_ac () -{ - $debug_cmd - - test -z "$configure_ac" \ - && func_autoconf_configure configure.ac && configure_ac=configure.ac - test -z "$configure_ac" \ - && func_autoconf_configure configure.in && configure_ac=configure.in - test -z "$configure_ac" \ - || func_verbose "found '$configure_ac'" - - require_configure_ac=: -} - - -# require_gnu_m4 -# -------------- -# Search for GNU M4, and export it in $M4. -require_gnu_m4=func_require_gnu_m4 -func_require_gnu_m4 () -{ - $debug_cmd - - test -n "$M4" || { - # Find the first m4 binary that responds to --version. - func_find_tool M4 gm4 gnum4 m4 - } - - test -n "$M4" || func_fatal_error "\ -Please install GNU M4, or 'export M4=/path/to/gnu/m4'." - - func_verbose "export M4='$M4'" - - # Make sure the search result is visible to subshells - export M4 - - require_gnu_m4=: -} - - -## --------------- ## -## Core functions. ## -## --------------- ## - -# This section contains the high level functions used when calling this -# file as a script. 'func_extract_trace' is probably the only one that you -# won't want to replace if you source this file into your own script. - - -# func_extract_trace MACRO_NAMES [FILENAME]... -# -------------------------------------------- -# set '$func_extract_trace_result' to a colon delimited list of arguments -# to any of the comma separated list of MACRO_NAMES in FILENAME. If no -# FILENAME is given, then '$configure_ac' is assumed. -func_extract_trace () -{ - $debug_cmd - - $require_configure_ac - $require_gnu_m4 - - _G_m4_traces=`$ECHO "--trace=$1" |$SED 's%,% --trace=%g'` - _G_re_macros=`$ECHO "($1)" |$SED 's%,%|%g'` - _G_macros="$1"; shift - test $# -gt 0 || { - set dummy $configure_ac - shift - } - - # Generate an error if the first file is missing - <"$1" - - # Sadly, we can't use 'autom4te' tracing to extract macro arguments, - # because it complains about things we want to ignore at bootstrap - # time - like missing m4_include files; AC_PREREQ being newer than - # the installed autoconf; and returns nothing when tracing - # 'AM_INIT_AUTOMAKE' when aclocal hasn't been generated yet. - # - # The following tries to emulate a less persnickety version of (and - # due to not having to wait for Perl startup on every invocation, - # it's probably faster too): - # - # autom4te --language=Autoconf --trace=$my_macro:\$% "$@" - # - # First we give a minimal set of macro declarations to M4 to prime - # it for reading Autoconf macros, while still providing some of the - # functionality generally used at m4-time to supply dynamic - # arguments to Autocof functions, but without following - # 'm4_s?include' files. - _G_mini=' - # Initialisation. - m4_changequote([,]) - m4_define([m4_copy], [m4_define([$2], m4_defn([$1]))]) - m4_define([m4_rename], [m4_copy([$1], [$2])m4_undefine([$1])]) - - # Disable these macros. - m4_undefine([m4_dnl]) - m4_undefine([m4_include]) - m4_undefine([m4_m4exit]) - m4_undefine([m4_m4wrap]) - m4_undefine([m4_maketemp]) - - # Copy and rename macros not handled by "m4 --prefix". - m4_define([dnl], [m4_builtin([dnl])]) - m4_copy([m4_define], [m4_defun]) - m4_rename([m4_ifelse], [m4_if]) - m4_ifdef([m4_mkstemp], [m4_undefine([m4_mkstemp])]) - m4_rename([m4_patsubst], [m4_bpatsubst]) - m4_rename([m4_regexp], [m4_bregexp]) - - # "m4sugar.mini" - useful m4-time macros for dynamic arguments. - # If we discover packages that need more m4 macros defined in - # order to bootstrap correctly, add them here: - m4_define([m4_bmatch], - [m4_if([$#], 0, [], [$#], 1, [], [$#], 2, [$2], - [m4_if(m4_bregexp([$1], [$2]), -1, - [$0([$1], m4_shift3($@))], [$3])])]) - m4_define([m4_ifndef], [m4_ifdef([$1], [$3], [$2])]) - m4_define([m4_ifset], - [m4_ifdef([$1], [m4_ifval(m4_defn([$1]), [$2], [$3])], [$3])]) - m4_define([m4_require], [$1]) - m4_define([m4_shift3], [m4_shift(m4shift(m4shift($@)))]) - - # "autoconf.mini" - things from autoconf macros we care about. - m4_copy([m4_defun], [AC_DEFUN]) - - # Dummy definitions for the macros we want to trace. - # AM_INIT_AUTOMAKE at least produces no trace without this. - ' - - _G_save=$IFS - IFS=, - for _G_macro in $_G_macros; do - IFS=$_G_save - func_append _G_mini "AC_DEFUN([$_G_macro])$nl" - done - IFS=$_G_save - - # We discard M4's stdout, but the M4 trace output from reading our - # "autoconf.mini" followed by any other files passed to this - # function is then scanned by sed to transform it into a colon - # delimited argument list assigned to a shell variable. - _G_transform='s|#.*$||; s|^dnl .*$||; s| dnl .*$||;' - - # Unfortunately, alternation in regexp addresses doesn't work in at - # least BSD (and hence Mac OS X) sed, so we have to append a capture - # and print block for each traced macro to the sed transform script. - _G_save=$IFS - IFS=, - for _G_macro in $_G_macros; do - IFS=$_G_save - func_append _G_transform ' - /^m4trace: -1- '"$_G_macro"'/ { - s|^m4trace: -1- '"$_G_macro"'[([]*|| - s|], [[]|:|g - s|[])]*$|:| - s|\(.\):$|\1| - p - }' - done - IFS=$_G_save - - # Save the command pipeline results for further use by callers of - # this function. - func_extract_trace_result=`$ECHO "$_G_mini" \ - |$M4 -daq --prefix $_G_m4_traces - "$@" 2>&1 1>/dev/null \ - |$SED -n -e "$_G_transform"` -} - - -# func_extract_trace_first MACRO_NAMES [FILENAME]... -# -------------------------------------------------- -# Exactly like func_extract_trace, except that only the first argument -# to the first invocation of one of the comma separated MACRO_NAMES is -# returned in '$func_extract_trace_first_result'. -func_extract_trace_first () -{ - $debug_cmd - - func_extract_trace ${1+"$@"} - func_extract_trace_first_result=`$ECHO "$func_extract_trace_result" \ - |$SED -e 's|:.*$||g' -e 1q` -} - - -# func_main [ARG]... -# ------------------ -func_main () -{ - $debug_cmd - - # Configuration. - usage='$progname MACRO_NAME FILE [...]' - - long_help_message=' -The first argument to this program is the name of an autotools macro -whose arguments you want to extract by examining the files listed in the -remaining arguments using the same tool that Autoconf and Automake use, -GNU M4. - -The arguments are returned separated by colons, with each traced call -on a separate line.' - - # Option processing. - func_options "$@" - eval set dummy "$func_options_result"; shift - - # Validate remaining non-option arguments. - test $# -gt 1 \ - || func_fatal_help "not enough arguments" - - # Pass non-option arguments to extraction function. - func_extract_trace "$@" - - # Display results. - test -n "$func_extract_trace_result" \ - && $ECHO "$func_extract_trace_result" - - # The End. - exit $EXIT_SUCCESS -} - - -## --------------------------- ## -## Actually perform the trace. ## -## --------------------------- ## - -# Only call 'func_main' if this script was called directly. -test extract-trace = "$progname" && func_main "$@" - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "20/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: - -# Set a version string for *this* script. -scriptversion=2014-11-04.13; # UTC - - -## ------------------- ## -## Hookable functions. ## -## ------------------- ## - -# After 'bootstrap.conf' has been sourced, execution proceeds by calling -# 'func_bootstrap'. Wherever a function is decorated with -# 'func_hookable func_name', you will find a matching 'func_run_hooks -# func_name', which executes all functions added with 'func_add_hook -# func_name my_func'. -# -# You might notice that many of these functions begin with a series of -# '$require_foo' lines. See the docu-comments at the start of the -# 'Resource management' section for a description of what these are. - - -# func_bootstrap [ARG]... -# ----------------------- -# All the functions called inside func_bootstrap are hookable. See the -# the individual implementations for details. -func_bootstrap () -{ - $debug_cmd - - # Save the current positional parameters to prevent them being - # corrupted by calls to 'set' in 'func_init'. - func_quote_for_eval ${1+"$@"} - _G_saved_positional_parameters=$func_quote_for_eval_result - - # Initialisation. - func_init - - # Option processing. - eval func_options "$_G_saved_positional_parameters" - - # Post-option preparation. - func_prep - - # Reconfigure the package. - func_reconfigure - - # Ensure .version is up-to-date. - func_update_dotversion - - # Finalisation. - func_fini -} - - -# func_init -# --------- -# Any early initialisations can be hooked to this function. Consider -# whether you can hook onto 'func_prep' instead, because if you hook -# any slow to execute code in here, it will also add to the time before -# './bootstrap --version' can respond. -func_hookable func_init -func_init () -{ - $debug_cmd - - func_run_hooks func_init -} - - -# func_prep -# --------- -# Function to perform preparation for remaining bootstrap process. If -# your hooked code relies on the outcome of 'func_options' hook it here -# rather than to 'func_init'. -# -# All the functions called inside func_prep are hookable. See the -# individual implementations for details. -func_hookable func_prep -func_prep () -{ - $debug_cmd - - $require_buildtools_uptodate - $require_checkout_only_file - - $require_gnulib_merge_changelog - - # Report the results of SED and GREP searches from funclib.sh. - func_verbose "GREP='$GREP'" - func_verbose "SED='$SED'" - - # fetch update files from the translation project - func_update_translations - - func_run_hooks func_prep -} - - -# func_update_translations -# ------------------------ -# Update package po files and translations. -func_hookable func_update_translations -func_update_translations () -{ - $debug_cmd - - $opt_skip_po || { - test -d po && { - $require_package - - func_update_po_files po $package || exit $? - } - - func_run_hooks func_update_translations - } -} - - -# func_reconfigure -# ---------------- -# Reconfigure the current package by running the appropriate autotools in a -# suitable order. -func_hookable func_reconfigure -func_reconfigure () -{ - $debug_cmd - - $require_automake_options - - # Automake (without 'foreign' option) requires that README exists. - case " $automake_options " in - " foreign ") ;; - *) func_ensure_README ;; - esac - - # Ensure ChangeLog presence. - if test -n "$gnulib_modules"; then - func_ifcontains "$gnulib_modules" gitlog-to-changelog \ - func_ensure_changelog - else - $require_gnulib_cache - if $SED -n '/^gl_MODULES(\[/,/^])$/p' $gnulib_cache 2>/dev/null | - func_grep_q gitlog-to-changelog - then - func_ensure_changelog - fi - fi - - # Released 'autopoint' has the tendency to install macros that have - # been obsoleted in current 'gnulib', so run this before 'gnulib-tool'. - func_autopoint - - # Autoreconf runs 'aclocal' before 'libtoolize', which causes spurious - # warnings if the initial 'aclocal' is confused by the libtoolized - # (or worse: out-of-date) macro directory. - func_libtoolize - - # If you need to do anything after 'gnulib-tool' is done, but before - # 'autoreconf' runs, you don't need to override this whole function, - # because 'func_gnulib_tool' is hookable. - func_gnulib_tool - - func_autoreconf - - func_run_hooks func_reconfigure -} - - -# func_gnulib_tool -# ---------------- -# Run 'gnulib-tool' to fetch gnulib modules into the current package. -# -# It's assumed that since you are using gnulib's 'bootstrap' script, -# you're also using gnulib elsewhere in your package. If not, then -# you can replace this function in 'bootstrap.conf' with: -# -# func_gnulib_tool () { :; } -# -# (although the function returns immediately if $gnulib_tool is set to -# true in any case). -func_hookable func_gnulib_tool -func_gnulib_tool () -{ - $debug_cmd - - $require_gnulib_tool - $require_libtoolize - - test true = "$gnulib_tool" || { - # bootstrap.conf written for gnulib bootstrap expects - # gnulib_tool_option_extras to which --no-changelog is appended, - # but libtool bootstrap expects you to append to gnulib_tool_options - # so that you can override the --no-changelog default: make sure we - # support both styles so users can migrate between them easily. - gnulib_tool_all_options="$gnulib_tool_options $gnulib_tool_option_extras" - - if test -n "$gnulib_modules"; then - $require_gnulib_cache - $require_gnulib_tool_base_options - - gnulib_mode=--import - - # Try not to pick up any stale values from 'gnulib-cache.m4'. - rm -f "$gnulib_cache" - - test -n "$gnulib_tool_base_options" \ - && func_append_uniq gnulib_tool_all_options " $gnulib_tool_base_options" - test -n "$gnulib_mk" \ - && func_append_uniq gnulib_tool_all_options " --makefile-name=$gnulib_mk" - test -n "$tests_base" && { - func_append_uniq gnulib_tool_all_options " --tests-base=$tests_base" - func_append_uniq gnulib_tool_all_options " --with-tests" - } - else - - # 'gnulib_modules' and others are cached in 'gnulib-cache.m4': - # Use 'gnulib --update' to fetch gnulib modules. - gnulib_mode=--update - fi - - # Add a sensible default libtool option to gnulib_tool_options. - # The embedded echo is to squash whitespace before globbing. - case `echo " "$gnulib_tool_all_options" "` in - *" --no-libtool "*|*" --libtool "*) ;; - *) if test true = "$LIBTOOLIZE"; then - func_append_uniq gnulib_tool_all_options " --no-libtool" - else - func_append_uniq gnulib_tool_all_options " --libtool" - fi - ;; - esac - - $opt_copy || func_append_uniq gnulib_tool_all_options " --symlink" - - func_append_uniq gnulib_tool_all_options " $gnulib_mode" - func_append gnulib_tool_all_options " $gnulib_modules" - - # The embedded echo is to squash whitespace before display. - gnulib_cmd=`echo $gnulib_tool $gnulib_tool_all_options` - - func_show_eval "$gnulib_cmd" 'exit $?' - - # Use 'gnulib-tool --copy-file' to install non-module files. - func_install_gnulib_non_module_files - } - - func_run_hooks func_gnulib_tool -} - - -# func_fini -# --------- -# Function to perform all finalisation for the bootstrap process. -func_hookable func_fini -func_fini () -{ - $debug_cmd - - func_gettext_configuration - func_clean_dangling_symlinks - func_clean_unused_macros - func_skip_po_recommendation - - func_run_hooks func_fini - - $require_bootstrap_uptodate - - func_echo "Done. Now you can run './configure'." -} - - -# func_gettext_configuration -# -------------------------- -# Edit configuration values into po/Makevars. -func_hookable func_gettext_configuration -func_gettext_configuration () -{ - $debug_cmd - - $require_autopoint - - test true = "$AUTOPOINT" || { - $require_copyright_holder - $require_extra_locale_categories - $require_package_bugreport - - # Escape xgettext options for sed Makevars generation below. - # We have to delete blank lines in a separate script so that we don't - # append \\\ to the penultimate line, and then delete the last empty - # line, which messes up the variable substitution later in this - # function. Note that adding a literal \\\ requires double escaping - # here, once for the execution subshell, and again for the assignment, - # which is why there are actually 12 (!!) backslashes in the script. - _G_xgettext_options=`echo "$xgettext_options$nl" |$SED '/^$/d' |$SED ' - $b - s|$| \\\\\\\\\\\\|'` - - # Create gettext configuration. - func_echo "Creating po/Makevars from po/Makevars.template ..." - $RM -f po/Makevars - $SED ' - /^EXTRA_LOCALE_CATEGORIES *=/s|=.*|= '"$extra_locale_categories"'| - /^COPYRIGHT_HOLDER *=/s|=.*|= '"$copyright_holder"'| - /^MSGID_BUGS_ADDRESS *=/s|=.*|= '"$package_bugreport"'| - /^XGETTEXT_OPTIONS *=/{ - s|$| \\| - a\ - '"$_G_xgettext_options"' \\\ - $${end_of_xgettext_options+} - } - ' po/Makevars.template >po/Makevars || exit 1 - } - - func_run_hooks func_gettext_configuration -} - - - -## --------------- ## -## Core functions. ## -## --------------- ## - -# This section contains the main functions called from the 'Hookable -# functions' (shown above), and are the ones you're most likely -# to want to replace with your own implementations in 'bootstrap.conf'. - - -# func_autopoint -# -------------- -# If this package uses gettext, then run 'autopoint'. -func_autopoint () -{ - $debug_cmd - - $require_autopoint - - test true = "$AUTOPOINT" \ - || func_show_eval "$AUTOPOINT --force" 'exit $?' -} - - -# func_libtoolize -# --------------- -# If this package uses libtool, then run 'libtoolize'. -func_libtoolize () -{ - $debug_cmd - - $require_libtoolize - - test true = "$LIBTOOLIZE" || { - _G_libtoolize_options= - $opt_copy && func_append _G_libtoolize_options " --copy" - $opt_force && func_append _G_libtoolize_options " --force" - $opt_verbose || func_append _G_libtoolize_options " --quiet" - func_show_eval "$LIBTOOLIZE$_G_libtoolize_options" 'exit $?' - } -} - - -# func_gnulib_tool_copy_file SRC DEST -# ----------------------------------- -# Copy SRC, a path relative to the gnulib sub-tree, to DEST, a path -# relative to the top-level source directory using gnulib-tool so that -# any patches or replacements in $local_gl_dir are applied. -func_gnulib_tool_copy_file () -{ - $debug_cmd - - $require_gnulib_tool - $require_patch - - if test true = "$gnulib_tool"; then - # If gnulib-tool is not available (e.g. bootstrapping in a - # distribution tarball), make sure that at least we have some - # version of the required file already in place. - test -f "$2" || func_fatal_error "\ -Can't find, copy or download '$2', a required -gnulib supplied file, please provide the location of a -complete 'gnulib' tree by setting 'gnulib_path' in your -'bootstrap.conf' or with the '--gnulib-srcdir' option - -or else specify the location of your 'git' binary by -setting 'GIT' in the environment so that a fresh -'gnulib' submodule can be cloned." - else - $require_gnulib_copy_cmd - - $gnulib_copy_cmd $1 $2 2>/dev/null || { - $require_gnulib_path - - func_error "'$gnulib_path/$1' does not exist" - return 1 - } - fi -} - - -# func_install_gnulib_non_module_files -# ------------------------------------ -# Get additional non-module files from gnulib, overriding existing files. -func_install_gnulib_non_module_files () -{ - $debug_cmd - - $require_build_aux - $require_gnulib_tool - - test -n "$gnulib_non_module_files" && { - maybe_exit_cmd=: - - for file in $gnulib_non_module_files; do - case $file in - */COPYING*) dest=COPYING;; - */INSTALL) dest=INSTALL;; - build-aux/missing) dest= - func_warning settings "\ -Please remove build-aux/missing from gnulib_module_files in -'bootstrap.conf', as it may clash with Automake's version." - ;; - build-aux/*) dest=$build_aux/`expr "$file" : 'build-aux/\(.*\)'`;; - *) dest=$file;; - esac - - # Be sure to show all copying errors before bailing out - test -z "$dest" \ - || func_gnulib_tool_copy_file "$file" "$dest" \ - || maybe_exit_cmd="exit $EXIT_FAILURE" - done - - $maybe_exit_cmd - } -} - - -# func_ensure_changelog -# --------------------- -# Even with 'gitlog-to-changelog' generated ChangeLogs, automake -# will not run to completion with no ChangeLog file. -func_ensure_changelog () -{ - $debug_cmd - - test -f ChangeLog && mv -f ChangeLog ChangeLog~ - - cat >ChangeLog <<'EOT' -## ---------------------- ## -## DO NOT EDIT THIS FILE! ## -## ---------------------- ## - -ChangeLog is generated by gitlog-to-changelog. -EOT - - _G_message="creating dummy 'ChangeLog'" - test -f ChangeLog~ \ - && func_append _G_message ' (backup in ChangeLog~)' - func_verbose "$_G_message" - - return 0 -} - - -# func_ensure_README -# ------------------ -# Without AM_INIT_AUTOMAKE([foreign]), automake will not run to -# completion with no README file, even though README.md or README.txt -# is often preferable. -func_ensure_README () -{ - $debug_cmd - - test -f README || { - _G_README= - for _G_readme in README.txt README.md README.rst; do - test -f "$_G_readme" && break - done - - test -f "$_G_readme" && $LN_S $_G_readme README - func_verbose "$LN_S $_G_readme README" - } - - return 0 -} - - -# func_autoreconf [SUBDIR] -# ------------------------ -# Being careful not to re-run 'autopoint' or 'libtoolize', and not to -# try to run 'autopoint', 'libtoolize' or 'autoheader' on packages that -# don't use them, defer to 'autoreconf' for execution of the remaining -# autotools to bootstrap this package. -# -# Projects with multiple trees to reconfigure can hook another call to -# this function onto func_reconfigure: -# -# my_autoreconf_foo () -# { -# func_autoreconf foo -# } -# func_add_hook func_reconfigure my_autoreconf_foo -func_autoreconf () -{ - $debug_cmd - - $require_autoheader - $require_build_aux # automake and others put files in here - $require_macro_dir # aclocal and others put files in here - - # We ran these manually already, and autoreconf won't exec ':' - save_AUTOPOINT=$AUTOPOINT; AUTOPOINT=true - save_LIBTOOLIZE=$LIBTOOLIZE; LIBTOOLIZE=true - - _G_autoreconf_options= - $opt_copy || func_append _G_autoreconf_options " --symlink" - $opt_force && func_append _G_autoreconf_options " --force" - $opt_verbose && func_append _G_autoreconf_options " --verbose" - func_show_eval "$AUTORECONF$_G_autoreconf_options --install${1+ $1}" 'exit $?' - - AUTOPOINT=$save_AUTOPOINT - LIBTOOLIZE=$save_LIBTOOLIZE -} - - -# func_check_configuration VARNAME [CONFIGURE_MACRO] -# -------------------------------------------------- -# Exit with a suitable diagnostic for an important configuration change -# that needs to be made before bootstrap can run correctly. -func_check_configuration () -{ - $debug_cmd - - $require_configure_ac - - eval 'test -n "$'$1'"' || { - _G_error_msg="please set '$1' in 'bootstrap.conf'" - if test -n "$configure_ac" && test -n "$2"; then - func_append _G_error_msg " -or add the following (or similar) to your '$configure_ac': -$2" - fi - - func_fatal_error "$_G_error_msg" - } -} - - -# func_clean_dangling_symlinks -# ---------------------------- -# Remove any dangling symlink matching "*.m4" or "*.[ch]" in some -# gnulib-populated directories. Such .m4 files would cause aclocal to -# fail. The following requires GNU find 4.2.3 or newer. Considering -# the usual portability constraints of this script, that may seem a very -# demanding requirement, but it should be ok. Ignore any failure, -# which is fine, since this is only a convenience to help developers -# avoid the relatively unusual case where a symlinked-to .m4 file is -# git-removed from gnulib between successive runs of this script. -func_clean_dangling_symlinks () -{ - $debug_cmd - - $require_macro_dir - $require_source_base - - func_verbose "cleaning dangling symlinks" - - find "$macro_dir" "$source_base" \ - -depth \( -name '*.m4' -o -name '*.[ch]' \) \ - -type l -xtype l -delete > /dev/null 2>&1 -} - - -# func_clean_unused_macros -# ------------------------ -# Autopoint can result in over-zealously adding macros into $macro_dir -# even though they are not actually used, for example tests to help -# build the 'intl' directory even though you have specified -# 'AM_GNU_GETTEXT([external])' in your configure.ac. This function -# looks removes any macro files that can be found in gnulib, but -# are not 'm4_include'd by 'aclocal.m4'. -func_clean_unused_macros () -{ - $debug_cmd - - $require_gnulib_path - $require_macro_dir - - test -n "$gnulib_path" && test -f aclocal.m4 && { - aclocal_m4s=`find . -name aclocal.m4 -print` - - # We use 'ls|grep' instead of 'ls *.m4' to avoid exceeding - # command line length limits in some shells. - for file in `cd "$macro_dir" && ls -1 |$GREP '\.m4$'`; do - - # Remove a macro file when aclocal.m4 does not m4_include it... - func_grep_q 'm4_include([[]'$macro_dir/$file'])' $aclocal_m4s \ - || test ! -f "$gnulib_path/m4/$file" || { - - # ...and there is an identical file in gnulib... - if func_cmp_s "$gnulib_path/m4/$file" "$macro_dir/$file"; then - - # ...and it's not in the precious list ('echo' is needed - # here to squash whitespace for the match expression). - case " "`echo $gnulib_precious`" " in - *" $file "*) ;; - *) rm -f "$macro_dir/$file" - func_verbose \ - "removing unused gnulib file '$macro_dir/$file'" - esac - fi - } - done - } -} - - -# func_skip_po_recommendation -# --------------------------- -# If there is a po directory, and '--skip-po' wasn't passed, let the -# user know that they can use '--skip-po' on subsequent invocations. -func_skip_po_recommendation () -{ - $debug_cmd - - test ! -d po \ - || $opt_skip_po \ - || func_warning recommend "\ -If your pofiles are up-to-date, you can rerun bootstrap -as '$progname --skip-po' to avoid redownloading." -} - - -# func_update_dotversion -# ---------------------- -# Even with 'gitlog-to-changelog' generated ChangeLogs, automake -# will not run to completion with no ChangeLog file. -func_update_dotversion () -{ - $debug_cmd - - test -f "$build_aux/git-version-gen" && { - _G_message="updating .version" - test -f .version && { - mv .version .version~ - func_append _G_message " (backup in .version~)" - } - func_verbose "updating .version" - - $build_aux/git-version-gen dummy-arg > .version - } -} - - - -## -------------------- ## -## Resource management. ## -## -------------------- ## - -# This section contains definitions for functions that each ensure a -# particular resource (a file, or a non-empty configuration variable for -# example) is available, and if appropriate to extract default values -# from pertinent package files. Where a variable already has a non- -# empty value (as set by the package's 'bootstrap.conf'), that value is -# used in preference to deriving the default. Call them using their -# associated 'require_*' variable to ensure that they are executed, at -# most, once. - - -# require_checkout_only_file -# -------------------------- -# Bail out if this package only bootstraps properly from a repository -# checkout. -require_checkout_only_file=func_require_checkout_only_file -func_require_checkout_only_file () -{ - $debug_cmd - - $opt_force || { - test -n "$checkout_only_file" && test ! -f "$checkout_only_file" \ - && func_fatal_error "\ -Bootstrapping from a non-checked-out distribution is risky. -If you wish to bootstrap anyway, use the '--force' option." - } - - require_checkout_only_file=: -} - - -# require_aclocal_amflags -# ----------------------- -# Ensure '$aclocal_amflags' has a sensible default, extracted from -# 'Makefile.am' if necessary. -require_aclocal_amflags=func_require_aclocal_amflags -func_require_aclocal_amflags () -{ - $debug_cmd - - $require_makefile_am - - _G_sed_extract_aclocal_amflags='s|#.*$|| - /^[ ]*ACLOCAL_AMFLAGS[ ]*=/ { - s|^.*=[ ]*\(.*\)|aclocal_amflags="\1"| - p - }' - - _G_aclocal_flags_cmd=`$SED -n "$_G_sed_extract_aclocal_amflags" \ - "$makefile_am"` - eval "$_G_aclocal_flags_cmd" - - func_verbose "ACLOCAL_AMFLAGS='$aclocal_amflags'" - - require_aclocal_amflags=: -} - - -# require_autoheader -# ------------------ -# Skip autoheader if it's not needed. -require_autoheader=func_require_autoheader -func_require_autoheader () -{ - $debug_cmd - - test true = "$AUTOHEADER" || { - func_extract_trace AC_CONFIG_HEADERS - test -n "$func_extract_trace_result" \ - || func_extract_trace AC_CONFIG_HEADER - - test -n "$func_extract_trace_result" || { - AUTOHEADER=true - - func_verbose "export AUTOHEADER='$AUTOHEADER'" - - # Make sure the search result is visible to subshells - export AUTOHEADER - } - } - - require_autoheader=: -} - - -# require_automake_options -# ------------------------ -# Extract options from AM_AUTOMAKE_INIT. -require_automake_options=func_require_automake_options -func_require_automake_options () -{ - $debug_cmd - - func_extract_trace AM_INIT_AUTOMAKE - automake_options=$func_extract_trace_result - - require_automake_options=: -} - - -# require_autopoint -# ----------------- -# Skip autopoint if it's not needed. -require_autopoint=func_require_autopoint -func_require_autopoint () -{ - $debug_cmd - - test true = "$AUTOPOINT" || { - func_extract_trace AM_GNU_GETTEXT_VERSION - - test -n "$func_extract_trace_result" || { - AUTOPOINT=true - - func_verbose "export AUTOPOINT='$AUTOPOINT'" - - # Make sure the search result is visible to subshells - export AUTOPOINT - } - } - - require_autopoint=: -} - - -# require_bootstrap_uptodate -# -------------------------- -# Complain if the version of bootstrap in the gnulib directory differs -# from the one we are running. -require_bootstrap_uptodate=func_require_bootstrap_uptodate -func_require_bootstrap_uptodate () -{ - $debug_cmd - - $require_build_aux - - _G_bootstrap_sources=" - $build_aux/bootstrap.in - $build_aux/extract-trace - $build_aux/funclib.sh - $build_aux/options-parser - " - - _G_missing_bootstrap_sources=false - for _G_src in $_G_bootstrap_sources; do - test -f "$_G_src" || _G_missing_bootstrap_sources=: - done - - if $_G_missing_bootstrap_sources; then - func_warning upgrade "\ -Please add bootstrap to your gnulib_modules list in -'bootstrap.conf', so that I can tell you when there are -updates available." - else - rm -f bootstrap.new - $build_aux/inline-source $build_aux/bootstrap.in > bootstrap.new - - if func_cmp_s "$progpath" bootstrap.new; then - rm -f bootstrap.new - func_verbose "bootstrap script up to date" - else - chmod 555 bootstrap.new - func_warning upgrade "\ -An updated bootstrap script has been generated for you in -'bootstrap.new'. After you've verified that you want -the changes, you can update with: - mv -f bootstrap.new $progname - ./$progname - -Or you can disable this check permanently by adding the -following to 'bootstrap.conf': - require_bootstrap_uptodate=:" - fi - fi - - require_bootstrap_uptodate=: -} - - -# require_build_aux -# ----------------- -# Ensure that '$build_aux' is set, and if it doesn't already point to an -# existing directory, create one. -require_build_aux=func_require_build_aux -func_require_build_aux () -{ - $debug_cmd - - test -n "$build_aux" || { - func_extract_trace_first AC_CONFIG_AUX_DIR - build_aux=$func_extract_trace_first_result - func_check_configuration build_aux \ - "AC_CONFIG_AUX_DIR([name of a directory for build scripts])" - - func_verbose "build_aux='$build_aux'" - } - - $require_vc_ignore_files - - # If the build_aux directory doesn't exist, create it now, and mark it - # as ignored for the VCS. - if test ! -d "$build_aux"; then - func_show_eval "mkdir '$build_aux'" - - test -n "$vc_ignore_files" \ - || func_insert_if_absent "$build_aux" $vc_ignore_files - fi - - require_build_aux=: -} - - -# require_buildreq_autobuild -# -------------------------- -# Try to find whether the bootstrap requires autobuild. -require_buildreq_autobuild=func_require_buildreq_autobuild -func_require_buildreq_autobuild () -{ - $debug_cmd - - $require_macro_dir - - test -f "$macro_dir/autobuild.m4" \ - || printf '%s\n' "$buildreq" |func_grep_q '^[ ]*autobuild' \ - || { - func_extract_trace AB_INIT - test -n "$func_extract_trace_result" && { - func_append buildreq 'autobuild - http://josefsson.org/autobuild/ -' - func_verbose "auto-adding 'autobuild' to build requirements" - } - } - - require_buildreq_autobuild=: -} - - -# require_buildreq_autoconf -# require_buildreq_autopoint -# require_buildreq_libtoolize -# --------------------------- -# Try to find the minimum compatible version of autoconf/libtool -# required to bootstrap successfully, and add it to '$buildreq'. -for tool in autoconf libtoolize autopoint; do - b=$tool - v=require_buildreq_${tool} - f=func_$v - case $tool in - autoconf) m=AC_PREREQ ;; - libtoolize) m=LT_PREREQ; b=libtool ;; - autopoint) m=AM_GNU_GETTEXT_VERSION b=gettext ;; - esac - - eval $v'='$f' - '$f' () - { - $debug_cmd - - # The following is ignored if undefined, but might be necessary - # in order for `func_find_tool` to run. - ${require_'$tool'-:} - - printf '\''%s\n'\'' "$buildreq" |func_grep_q '\''^[ ]*'$tool\'' || { - func_extract_trace '$m' - _G_version=$func_extract_trace_result - test -n "$_G_version" && { - func_append buildreq "\ - '$tool' $_G_version http://www.gnu.org/s/'$b' -" - func_verbose \ - "auto-adding '\'$tool'-$_G_version'\'' to build requirements" - } - } - - '$v'=: - } -' -done - - -# require_buildreq_automake -# ------------------------- -# Try to find the minimum compatible version of automake required to -# bootstrap successfully, and add it to '$buildreq'. -require_buildreq_automake=func_require_buildreq_automake -func_require_buildreq_automake () -{ - $debug_cmd - - # if automake is not already listed in $buildreq... - printf '%s\n' "$buildreq" |func_grep_q automake || { - func_extract_trace AM_INIT_AUTOMAKE - - # ...and AM_INIT_AUTOMAKE is declared... - test -n "$func_extract_trace_result" && { - automake_version=`$ECHO "$func_extract_trace_result" \ - |$SED -e 's|[^0-9]*||' -e 's| .*$||'` - test -n "$automake_version" || automake_version=- - - func_append buildreq "\ - automake $automake_version http://www.gnu.org/s/automake -" - func_verbose \ - "auto-adding 'automake-$automake_version' to build requirements" - } - } - - require_buildreq_automake=: -} - - -# require_buildreq_patch -# ---------------------- -# Automatically add a patch build-requirement if there are diff files -# in $local_gl_dir. -require_buildreq_patch=func_require_buildreq_patch -func_require_buildreq_patch () -{ - $debug_cmd - - $require_local_gl_dir - - # This ensures PATCH is set appropriately by the time - # func_check_versions enforces $buildreq. - $require_patch - - # If patch is not already listed in $buildreq... - printf '%s\n' "$buildreq" |func_grep_q '^[ ]*patch' || { - # The ugly find invocation is necessary to exit with non-zero - # status for old find binaries that don't support -exec fully. - if test ! -d "$local_gl_dir" \ - || find "$local_gl_dir" -name "*.diff" -exec false {} \; ; then : - else - func_append buildreq 'patch - http://www.gnu.org/s/patch -' - fi - } - - require_buildreq_patch=: -} - - -# require_buildtools_uptodate -# --------------------------- -# Ensure all the packages listed in BUILDREQS are available on the build -# machine at the minimum versions or better. -require_buildtools_uptodate=func_require_buildtools_uptodate -func_require_buildtools_uptodate () -{ - $debug_cmd - - $require_buildreq_autobuild - $require_buildreq_autoconf - $require_buildreq_automake - $require_buildreq_libtoolize - $require_buildreq_autopoint - $require_buildreq_patch - - test -n "$buildreq" && { - _G_error_hdr= - - func_check_versions $buildreq - $func_check_versions_result || { - test -n "$buildreq_readme" \ - && test -f "$buildreq_readme" \ - && _G_error_hdr="\ -$buildreq_readme explains how to obtain these prerequisite programs: -" - func_strtable 0 11 12 36 \ - "Program" "Min_version" "Homepage" $buildreq - func_fatal_error "$_G_error_hdr$func_strtable_result" - } - } - - require_buildtools_uptodate=: -} - - -# require_copyright_holder -# ------------------------ -# Ensure there is a sensible non-empty default value in '$copyright_holder'. -require_copyright_holder=func_require_copyright_holder -func_require_copyright_holder () -{ - $debug_cmd - - test -n "$copyright_holder" || { - copyright_holder='Free Software Foundation, Inc.' - func_warning settings "\ -Please set copyright_holder explicitly in 'bootstrap.conf'; -defaulting to '$copyright_holder'." - } - - require_copyright_holder=: -} - - -# require_doc_base -# ---------------- -# Ensure doc_base has a sensible value, extracted from 'gnulib-cache.m4' -# if possible, otherwise letting 'gnulib-tool' pick a default. -require_doc_base=func_require_doc_base -func_require_doc_base () -{ - $debug_cmd - - $require_gnulib_cache - - test -f "$gnulib_cache" && test -z "$doc_base" && { - func_extract_trace_first "gl_DOC_BASE" "$gnulib_cache" - doc_base=$func_extract_trace_first_result - - test -n "$doc_base" && func_verbose "doc_base='$doc_base'" - } - - require_doc_base=: -} - - -# require_dotgitmodules -# --------------------- -# Ensure we have a '.gitmodules' file, with appropriate 'gnulib' settings. -require_dotgitmodules=func_require_dotgitmodules -func_require_dotgitmodules () -{ - $debug_cmd - - $require_git - - test true = "$GIT" || { - # A gnulib entry in .gitmodules always takes precedence. - _G_path=`$GIT config --file .gitmodules submodule.gnulib.path 2>/dev/null` - - test -n "$_G_path" || { - $require_vc_ignore_files - - func_verbose "creating '.gitmodules'" - - # If the .gitmodules file doesn't exist, create it now, and mark - # it as ignored for the VCS. - test -n "$gnulib_path" || gnulib_path=gnulib - test -n "$gnulib_url" || gnulib_url=git://git.sv.gnu.org/gnulib - - { - echo '[submodule "gnulib"]' - echo " path = $gnulib_path" - echo " url = $gnulib_url" - } >> .gitmodules - - test -n "$vc_ignore_files" \ - || func_insert_if_absent ".gitmodules" $vc_ignore_files - } - } - - require_dotgitmodules=: -} - - -# require_extra_locale_categories -# ------------------------------- -# Ensure there is a default value in '$extra_locale_categories' -require_extra_locale_categories=func_require_extra_locale_categories -func_require_extra_locale_categories () -{ - $debug_cmd - - # Defaults to empty, so run with whatever value may have been set in - # 'bootstrap.conf'. - require_extra_locale_categories=: -} - - -# require_git -# ----------- -# Ignore git if it's not available, or we're not in a git checkout tree. -require_git=func_require_git -func_require_git () -{ - $debug_cmd - - $opt_skip_git && GIT=true - - test true = "$GIT" || { - if test -d .git/.; then - ($GIT --version) >/dev/null 2>&1 || GIT=true - fi - } - - func_verbose "GIT='$GIT'" - - require_git=: -} - - -# require_gnulib_cache -# -------------------- -# Ensure there is a non-empty default for '$gnulib_cache', and that it -# names an existing file. -require_gnulib_cache=func_require_gnulib_cache -func_require_gnulib_cache () -{ - $debug_cmd - - $require_macro_dir - - test -n "$gnulib_cache" \ - || gnulib_cache=$macro_dir/gnulib-cache.m4 - - func_verbose "found '$gnulib_cache'" - - require_gnulib_cache=: -} - - -# require_gnulib_copy_cmd -# ----------------------- -# Only calculate the options for copying files with gnulib once. -require_gnulib_copy_cmd=func_require_gnulib_copy_cmd -func_require_gnulib_copy_cmd () -{ - $debug_cmd - - $require_gnulib_tool - $require_gnulib_tool_base_options - - gnulib_copy_cmd="$gnulib_tool $gnulib_tool_base_options --copy-file" - $opt_copy || func_append gnulib_copy_cmd " --symlink" - $opt_quiet || func_append gnulib_copy_cmd " --verbose" - - require_gnulib_copy_cmd=: -} - - -# require_gnulib_merge_changelog -# ------------------------------ -# See if we can use gnulib's git-merge-changelog merge driver. -require_gnulib_merge_changelog=func_require_gnulib_merge_changelog -func_require_gnulib_merge_changelog () -{ - $debug_cmd - - test -f ChangeLog && { - $require_git - - func_grep_q '^\(/\|\)ChangeLog$' .gitignore || test true = "$GIT" || { - if $GIT config merge.merge-changelog.driver >/dev/null; then - : - elif (git-merge-changelog --version) >/dev/null 2>&1; then - func_echo "initializing git-merge-changelog driver" - $GIT config merge.merge-changelog.name 'GNU-style ChangeLog merge driver' - $GIT config merge.merge-changelog.driver 'git-merge-changelog %O %A %B' - else - func_warning recommend \ - "Consider installing git-merge-changelog from gnulib." - fi - } - } - - require_gnulib_merge_changelog=: -} - - -# require_gnulib_mk -# ----------------- -# Ensure gnulib_mk has a sensible value, extracted from 'gnulib-cache.m4' -# if possible, otherwise letting 'gnulib-tool' pick a default. -require_gnulib_mk=func_require_gnulib_mk -func_require_gnulib_mk () -{ - $debug_cmd - - $require_gnulib_cache - - test -f "$gnulib_cache" && test -z "$gnulib_mk" && { - func_extract_trace_first "gl_MAKEFILE_NAME" "$gnulib_cache" - gnulib_mk=$func_extract_trace_first_result - - test -n "$gnulib_mk" && func_verbose "gnulib_mk='$gnulib_mk'" - } - - require_gnulib_mk=: -} - - -# require_gnulib_name -# ------------------- -# Ensure gnulib_name has a sensible value, extracted from 'gnulib-cache.m4' -# if possible, otherwise letting 'gnulib-tool' pick a default. -require_gnulib_name=func_require_gnulib_name -func_require_gnulib_name () -{ - $debug_cmd - - $require_gnulib_cache - - test -f "$gnulib_cache" && test -z "$gnulib_name" && { - func_extract_trace_first "gl_LIB" "$gnulib_cache" - gnulib_name=$func_extract_trace_first_result - - test -n "$gnulib_name" && func_verbose "gnulib_name='$gnulib_name'" - } - - require_gnulib_name=: -} - - -# require_gnulib_path -# require_gnulib_url -# ------------------- -# Ensure 'gnulib_path' and 'gnulib_url' are set. -require_gnulib_path=func_require_dotgitmodules_parameters -require_gnulib_url=func_require_dotgitmodules_parameters -func_require_dotgitmodules_parameters () -{ - $debug_cmd - - $require_git - - test true = "$GIT" && { - # If we can't find git (or if the user specified '--skip-git'), - # then use an existing gnulib directory specified with - # '--gnulib-srcdir' if possible. - test -n "$gnulib_path" \ - || test ! -x "$opt_gnulib_srcdir/gnulib-tool" \ - || gnulib_path=$opt_gnulib_srcdir - } - - - $require_dotgitmodules - - test -f .gitmodules && { - # Extract the parameters with sed, since git may be missing - test -n "$gnulib_path" \ - || gnulib_path=`$SED -e '/^.submodule "gnulib".$/,${ - /[ ]*path *= */{ - s|[ ]*||g;s|^[^=]*=||;p - } - } - d' .gitmodules |$SED 1q` - test -n "$gnulib_url" \ - || gnulib_url=`$SED -e '/^.submodule "gnulib".$/,${ - /[ ]*url *= */{ - s|[ ]*||g;s|^[^=]*=||;p - } - } - d' .gitmodules |$SED 1q` - - func_verbose "gnulib_path='$gnulib_path'" - func_verbose "gnulib_url='$gnulib_url'" - } - - require_gnulib_path=: - require_gnulib_url=: -} - - -# require_gnulib_submodule -# ------------------------ -# Ensure that there is a current gnulib submodule at '$gnulib_path'. -require_gnulib_submodule=func_require_gnulib_submodule -func_require_gnulib_submodule () -{ - $debug_cmd - - $require_git - - if test true = "$GIT"; then - func_warning recommend \ - "No 'git' found; imported gnulib modules may be outdated." - else - $require_gnulib_path - $require_gnulib_url - - if test -f .gitmodules && test -f "$gnulib_path/gnulib-tool"; then - : All present and correct. - - elif test -n "$opt_gnulib_srcdir"; then - # Older git can't clone into an empty directory. - rmdir "$gnulib_path" 2>/dev/null - func_show_eval "$GIT clone --reference '$opt_gnulib_srcdir' \ - '$gnulib_url' '$gnulib_path'" \ - || func_fatal_error "Unable to fetch gnulib submodule." - - # Without --gnulib-srcdir, and no existing checked out submodule, we - # create a new shallow clone of the remote gnulib repository. - else - trap func_cleanup_gnulib 1 2 13 15 - - shallow= - $GIT clone -h 2>&1 |func_grep_q -- --depth \ - && shallow='--depth 365' - - func_show_eval "$GIT clone $shallow '$gnulib_url' '$gnulib_path'" \ - func_cleanup_gnulib - - # FIXME: Solaris /bin/sh will try to execute '-' if any of - # these signals are caught after this. - trap - 1 2 13 15 - fi - - # Make sure we've checked out the correct revision of gnulib. - func_show_eval "$GIT submodule init -- $gnulib_path" \ - && func_show_eval "$GIT submodule update -- $gnulib_path" \ - || func_fatal_error "Unable to update gnulib submodule." - fi - - require_gnulib_submodule=: -} - - -# require_gnulib_tool -# ------------------- -# Ensure that '$gnulib_tool' is set, and points to an executable file, -# or else fall back to using the binary 'true' if the main gnulib -# files appear to have been imported already. -require_gnulib_tool=func_require_gnulib_tool -func_require_gnulib_tool () -{ - $debug_cmd - - test true = "$gnulib_tool" || { - $require_gnulib_submodule - $require_gnulib_path - - test -n "$gnulib_tool" \ - || gnulib_tool=$gnulib_path/gnulib-tool - - test -x "$gnulib_tool" || { - gnulib_tool=true - func_warning recommend \ - "No 'gnulib-tool' found; gnulib modules may be missing." - } - - test true = "$gnulib_tool" \ - || func_verbose "found '$gnulib_tool'" - } - - require_gnulib_tool=: -} - - -# require_gnulib_tool_base_options -# -------------------------------- -# Ensure that '$gnulib_tool_base_options' contains all the base options -# required according to user configuration from bootstrap.conf. -require_gnulib_tool_base_options=func_require_gnulib_tool_base_options -func_require_gnulib_tool_base_options () -{ - $debug_cmd - - $require_gnulib_tool - - gnulib_tool_base_options= - - test true = "$gnulib_tool" || { - # 'gnulib_modules' and others are maintained in 'bootstrap.conf': - # Use 'gnulib --import' to fetch gnulib modules. - $require_build_aux - test -n "$build_aux" \ - && func_append_uniq gnulib_tool_base_options " --aux-dir=$build_aux" - $require_macro_dir - test -n "$macro_dir" \ - && func_append_uniq gnulib_tool_base_options " --m4-base=$macro_dir" - $require_doc_base - test -n "$doc_base" \ - && func_append_uniq gnulib_tool_base_options " --doc-base=$doc_base" - $require_gnulib_name - test -n "$gnulib_name" \ - && func_append_uniq gnulib_tool_base_options " --lib=$gnulib_name" - $require_local_gl_dir - test -n "$local_gl_dir" \ - && func_append_uniq gnulib_tool_base_options " --local-dir=$local_gl_dir" - $require_source_base - test -n "$source_base" \ - && func_append_uniq gnulib_tool_base_options " --source-base=$source_base" - } - - require_gnulib_tool_base_options=: -} - - -# require_libtoolize -# ------------------ -# Skip libtoolize if it's not needed. -require_libtoolize=func_require_libtoolize -func_require_libtoolize () -{ - $debug_cmd - - # Unless we're not searching for libtool use by this package, set - # LIBTOOLIZE to true if none of 'LT_INIT', 'AC_PROG_LIBTOOL' and - # 'AM_PROG_LIBTOOL' are used in configure. - test true = "$LIBTOOLIZE" || { - func_extract_trace LT_INIT - test -n "$func_extract_trace_result" || func_extract_trace AC_PROG_LIBTOOL - test -n "$func_extract_trace_result" || func_extract_trace AM_PROG_LIBTOOL - test -n "$func_extract_trace_result" || LIBTOOLIZE=true - } - - test -n "$LIBTOOLIZE" || { - # Find libtoolize, named glibtoolize in Mac Ports, but prefer - # user-installed libtoolize to ancient glibtoolize shipped by - # Apple with Mac OS X when Mac Ports is not installed. - func_find_tool LIBTOOLIZE libtoolize glibtoolize - } - - test -n "$LIBTOOLIZE" || func_fatal_error "\ -Please install GNU Libtool, or 'export LIBTOOLIZE=/path/to/libtoolize'." - - func_verbose "export LIBTOOLIZE='$LIBTOOLIZE'" - - # Make sure the search result is visible to subshells - export LIBTOOLIZE - - require_libtoolize=: -} - - -# require_local_gl_dir -# -------------------- -# Ensure local_gl_dir has a sensible value, extracted from 'gnulib-cache.m4' -# if possible, otherwise letting 'gnulib-tool' pick a default. -require_local_gl_dir=func_require_local_gl_dir -func_require_local_gl_dir () -{ - $debug_cmd - - $require_gnulib_cache - - test -f "$gnulib_cache" && test -z "$local_gl_dir" && { - func_extract_trace_first "gl_LOCAL_DIR" "$gnulib_cache" - local_gl_dir=$func_extract_trace_first_result - - test -n "$local_gl_dir" && func_verbose "local_gl_dir='$local_gl_dir'" - } - - require_local_gl_dir=: -} - - -# require_macro_dir -# ----------------- -# Ensure that '$macro_dir' is set, and if it doesn't already point to an -# existing directory, create one. -require_macro_dir=func_require_macro_dir -func_require_macro_dir () -{ - $debug_cmd - - # Sometimes this is stored in 'configure.ac'. - test -n "$macro_dir" || { - # AC_CONFIG_MACRO_DIRS takes a space delimited list of directories, - # but we only care about the first one in bootstrap. - func_extract_trace_first AC_CONFIG_MACRO_DIRS - macro_dir=`expr "x$func_extract_trace_first_result" : 'x\([^ ]*\)'` - } - test -n "$macro_dir" || { - func_extract_trace_first AC_CONFIG_MACRO_DIR - macro_dir=$func_extract_trace_first_result - } - - # Otherwise we might find it in 'Makefile.am'. - test -n "$macro_dir" || { - $require_aclocal_amflags - - # Take the argument following the first '-I', if any. - _G_minus_I_seen=false - for _G_arg in $aclocal_amflags; do - case $_G_minus_I_seen,$_G_arg in - :,*) macro_dir=$_G_arg; break ;; - *,-I) _G_minus_I_seen=: ;; - *,-I*) macro_dir=`expr x$_G_arg : 'x-I\(.*\)$'`; break ;; - esac - done - } - - func_verbose "macro_dir='$macro_dir'" - - func_check_configuration macro_dir \ - "AC_CONFIG_MACRO_DIRS([name of a directory for configure m4 files])" - - $require_vc_ignore_files - - # If the macro_dir directory doesn't exist, create it now, and mark it - # as ignored for the VCS. - if test ! -d "$macro_dir"; then - mkdir "$macro_dir" || func_permissions_error "$macro_dir" - - test -n "$vc_ignore_files" \ - || func_insert_if_absent "$macro_dir" $vc_ignore_files - fi - - require_macro_dir=: -} - - -# require_makefile_am -# ------------------- -# Ensure there is a 'Makefile.am' in the current directory. -require_makefile_am=func_require_makefile_am -func_require_makefile_am () -{ - $debug_cmd - - test -n "$makefile_am" \ - || makefile_am=Makefile.am - - <"$makefile_am" - - func_verbose "found '$makefile_am'" - - require_makefile_am=: -} - - -# require_package -# --------------- -# Ensure that '$package' contains a sensible default value. -require_package=func_require_package -func_require_package () -{ - $debug_cmd - - test -n "$package" || { - $require_package_name - - package=`echo "$package_name" \ - |$SED -e 's/GNU //' \ - -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` - } - - func_verbose "package='$package'" - - require_package=: -} - - -# require_package_bugreport -# ------------------------- -# Ensure that this has a sensible value, extracted from 'configure.ac' -# if appropriate (and possible!). -require_package_bugreport=func_require_package_bugreport -func_require_package_bugreport () -{ - $debug_cmd - - func_extract_trace AC_INIT - - save_ifs=$IFS - IFS=: - set dummy $func_extract_trace_result - IFS=$save_ifs - shift - - test -n "$package_bugreport" || package_bugreport=$3 - func_check_configuration package_bugreport \ - "AC_INIT([$package_name], [$package_version], [bug-$package@gnu.org])" - func_verbose "package_bugreport='$package_bugreport'" - - require_package_bugreport=: -} - - -# require_package_name -# -------------------- -# Ensure that this has a sensible value, extracted from 'configure.ac' -# if appropriate (and possible!). -require_package_name=func_require_package_name -func_require_package_name () -{ - $debug_cmd - - func_extract_trace AC_INIT - - save_ifs=$IFS - IFS=: - set dummy $func_extract_trace_result - IFS=$save_ifs - shift - - test -n "$package_name" || package_name=$1 - func_check_configuration package_name \ - "AC_INIT([name of your package], [package version number])" - func_verbose "package_name='$package_name'" - - require_package_name=: -} - - -# require_package_version -# ----------------------- -# Ensure that this has a sensible value, extracted from 'configure.ac' -# if appropriate (and possible!). While we might have set all the -# parameters extracted from AC_INIT at once, 'package_version' in -# particular is not necessarily available as early as the others, since -# 'git-version-gen' is often involved, and until then we can't rely on -# getting a correct version number from an AC_INIT extraction. -require_package_version=func_require_package_version -func_require_package_version () -{ - $debug_cmd - - func_extract_trace AC_INIT - - save_ifs=$IFS - IFS=: - set dummy $func_extract_trace_result - IFS=$save_ifs - shift - - test -n "$package_version" || package_version=$2 - test -n "$package_version" || { - # The embedded echo is to squash whitespace before globbing. - case " "`echo $gnulib_modules`" " in - *" git-version-gen "*) - func_fatal_error "\ -cannot \$require_package_version in bootstrap.conf before -func_gnulib_tool has installed the 'git-version-gen' script." - ;; - *) - func_check_configuration package_version \ - "AC_INIT([name of your package], [package version number])" - ;; - esac - } - func_verbose "package_version='$package_version'" - - require_package_version=: -} - - -# require_patch -# ------------- -# Find patch, according to the PATCH environment variable, or else -# searching the user's PATH. -require_patch=func_require_patch -func_require_patch () -{ - $debug_cmd - - test -n "$PATCH" || { - # Find a patch program, preferring gpatch, which is usually better - # than the vendor patch. - func_find_tool PATCH gpatch patch - } - - test -n "$PATCH" || func_fatal_error "\ -Please install GNU Patch, or 'export PATCH=/path/to/gnu/patch'." - - func_verbose "export PATCH='$PATCH'" - - # Make sure the search result is visible to subshells - export PATCH - - require_patch=: -} - - -# require_source_base -# ------------------- -# Ensure that source_base has a sensible value, extracted from -# 'gnulib-cache.m4' if possible. -require_source_base=func_require_source_base -func_require_source_base () -{ - $debug_cmd - - $require_gnulib_cache - - test -f "$gnulib_cache" && test -z "$source_base" && { - func_extract_trace_first "gl_SOURCE_BASE" "$gnulib_cache" - - source_base=$func_extract_trace_first_result - - func_verbose "source_base='$source_base'" - } - - require_source_base=: -} - - -# require_vc_ignore_files -# ----------------------- -# Ensure that '$vc_ignore' has been processed to list VCS ignore files -# in '$vc_ignore_files' -require_vc_ignore_files=func_require_vc_ignore_files -func_require_vc_ignore_files () -{ - $debug_cmd - - test -n "$vc_ignore" || vc_ignore=auto - - if test auto = "$vc_ignore" && test -z "$vc_ignore_files"; then - vc_ignore_files= - test -d .git && vc_ignore_files=.gitignore - test -d CVS && vc_ignore_files="$vc_ignore_files .cvsignore" - else - vc_ignore_files=$vc_ignore - fi - - func_verbose "vc_ignore_files='$vc_ignore_files'" - - require_vc_ignore_files=: -} - - -## ----------------- ## -## Helper functions. ## -## ----------------- ## - -# This section contains the helper functions used by the rest of 'bootstrap'. - -# func_len STRING -# --------------- -# STRING may not start with a hyphen. -if (eval 'x=123; test x${#x} = "x3"') 2>/dev/null -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_len () - { - $debug_cmd - - func_len_result=${#1} - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_len () - { - $debug_cmd - - func_len_result=`expr "$1" : ".*" 2>/dev/null || echo 0` - } -fi - - -# func_unset VAR -# -------------- -# Portably unset VAR. -# In some shells, an 'unset VAR' statement leaves a non-zero return -# status if VAR is already unset, which might be problematic if the -# statement is used at the end of a function (thus poisoning its return -# value) or when 'set -e' is active (causing even a spurious abort of -# the script in this case). -func_unset () -{ - { eval $1=; unset $1; } -} -unset=func_unset - - -# func_cmp_s FILE1 FILE2 -# ---------------------- -# Return non-zero exit status unless FILE1 and FILE2 are identical, without -# any output at all, even error messages. -func_cmp_s () -{ - $debug_cmd - - # This function relies on non-zero exit status, which will cause the - # program to exit when running in 'set -e' mode. - $CMP "$@" >/dev/null 2>&1 -} - - -# func_grep_q EXPRESSION [FILENAME..] -# ----------------------------------- -# Check whether EXPRESSION matches any line of any listed FILENAME, -# without any output at all, even error messages. -func_grep_q () -{ - $debug_cmd - - # This function relies on non-zero exit status, which will cause the - # program to exit when running in 'set -e' mode. - $GREP "$@" >/dev/null 2>&1 -} - - -# func_ifcontains LIST MEMBER YES-CMD [NO-CMD] -# -------------------------------------------- -# If whitespace-separated LIST contains MEMBER then execute YES-CMD, -# otherwise if NO-CMD was given, execute that. -func_ifcontains () -{ - $debug_cmd - - _G_wslist=$1 - _G_member=$2 - _G_yes_cmd=$3 - _G_no_cmd=${4-":"} - - _G_found=false - for _G_item in $_G_wslist; do - test "x$_G_item" = "x$_G_member" && { - _G_found=: - break - } - done - if $_G_found; then - eval "$_G_yes_cmd" - _G_status=$? - else - eval "$_G_no_cmd" - _G_status=$? - fi - - test 0 -eq "$_G_status" || exit $_G_status -} - - -# func_strpad STR WIDTH CHAR -# -------------------------- -# Trim STR, or pad with CHAR to force a total length of WIDTH. -func_strpad () -{ - $debug_cmd - - _G_width=`expr "$2" - 1` - func_strpad_result=`$ECHO "$1" |$SED ' - :a - s|^.\{0,'"$_G_width"'\}$|&'"$3"'| - ta - '` -} - - -# func_strrpad STR WIDTH CHAR -# --------------------------- -# Trim STR, or right-justify-pad with CHAR to force a total length of -# WIDTH. -func_strrpad () -{ - $debug_cmd - - _G_width=`expr "$2" - 1` - func_strrpad_result=`$ECHO "$1" |$SED ' - :a - s|^.\{0,'"$_G_width"'\}$|'"$3"'&| - ta - '` -} - - -# func_strrow INDENT FIELD WIDTH [FIELDn WIDTHn]... -# ------------------------------------------------- -# Return a string containing each FIELD left justified to WIDTH, with -# the whole thing indented by INDENT spaces. This function is used to -# render one row of aligned columns for a table by func_strtable(). -func_strrow () -{ - $debug_cmd - - func_strrow_linelen=$1; shift - - _G_row= - while test $# -gt 0; do - func_strrow_linelen=`expr $func_strrow_linelen + $2` - func_strpad "$1" $2 " " - func_append _G_row "$func_strpad_result" - shift; shift - done - - func_strrpad "$_G_row" $func_strrow_linelen " " - func_strrow_result=$func_strrpad_result -} - - -# func_strtable INDENT WIDTH1...WIDTHn HEADER1...HEADERn FIELD1...FIELDn -# ---------------------------------------------------------------------- -# Generate a string of newline-separated rows arranged in lined-up -# columns of the given WIDTHs, with the entire table indented by INDENT -# spaces. The number of columns is determined by the number of integer -# valued WIDTH arguments following INDENT. The next set (i.e. a number -# of arguments equal to the number of WIDTH arguments) of fields are -# treated as the table's column HEADERs, and are separated from the -# remainder of the table by an indented row of '-' characters. Remaining -# arguments are each aligned below the next available header, wrapping -# to a new row as necessary. Finally another row of '-' characters is -# added to mark the end of the table. -# -# For example an unindented 3 column table with 2 rows of data would be -# generated by this call: -# -# func_strtable 3 20 10 25 \ -# Header1 Header2 Header3 \ -# Row1Col1 Row1Col2 Row1Col3 \ -# Row2Col1 Row2Col2 Row2Col3 -# -# returning the following string: -# -# " Header1 Header2 Header3 -# ------------------------------------------------------- -# Row1Col1 Row1Col2 Row1Col3 -# Row2Col1 Row2Col2 Row2Col3 -# -------------------------------------------------------" -func_strtable () -{ - $debug_cmd - - # Save the indent value, we'll need it for each row we render. - _G_indent=$1; shift - - # Collect remaining numeric args into a list for reuse between - # members of each row when we call func_strrow later. - _G_widths=$1; shift - while test 0 -lt `expr "$1" : '[1-9][0-9]*$'`; do - func_append _G_widths " $1"; shift - done - - # Extract the same number of positional parameters as there are - # width elements - we'll do the header rows separately so that - # we can insert a divider line. - _G_header=$_G_indent - for _G_width in $_G_widths; do - func_append _G_header " $1 $_G_width"; shift - done - func_strrow $_G_header - - # Strip off the indent, and make a divider with '-' chars, then - # reindent. - _G_divider=`$ECHO "$func_strrow_result" \ - |$SED 's|[^ ]|-|g - :a - s|- |--|g - ta - '` - - # Append the header and divider to the running result. - func_append func_strtable_result "\ -$func_strrow_result -$_G_divider -" - - # The remaining rows are zipped between the width values we - # unwound earlier just like the header row above. - while test $# -gt 0; do - _G_row=$_G_indent - for _G_width in $_G_widths; do - func_append _G_row " $1 $_G_width"; shift - done - func_strrow $_G_row - func_append func_strtable_result "\ -$func_strrow_result -" - done - - # Mark the end of the table with a final divider line. - func_append func_strtable_result "$_G_divider" -} - - -# func_internal_error ARG... -# -------------------------- -# Echo program name prefixed message to standard error, and exit. -func_internal_error () -{ - func_fatal_error "\ -INTERNAL: " ${1+"$@"} " - Please report this bug to 'bug-gnulib@gnu.org' - in as much detail as possible." -} - - -# func_permissions_error FILE-OR-DIRECTORY -# ---------------------------------------- -# Echo program name prefixed permissions error message to standard -# error, and exit. -func_permissions_error () -{ - $debug_cmd - - func_fatal_error "Failed to create '$1', check permissions." -} - - -# func_show_eval CMD [FAIL_EXP] -# ----------------------------- -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () -{ - $debug_cmd - - $require_term_colors - - _G_cmd=$1 - _G_fail_exp=${2-':'} - - ${opt_silent-'false'} || { - func_quote_for_eval $_G_cmd - eval func_truncate_cmd $func_quote_for_eval_result - func_echo "running: $tc_bold$func_truncate_cmd_result$tc_reset" - } - - ${opt_dry_run-'false'} || { - eval "$_G_cmd" - _G_status=$? - test 0 -eq "$_G_status" || eval "(exit $_G_status); $_G_fail_exp" - } -} - - -# func_truncate_cmd CMD [ARG]... -# ------------------------------ -# For unreasonably long commands (such as a gnulib-tool invocation with -# the full module list for import), truncate CMD after the second non- -# option ARG. -func_truncate_cmd () -{ - $debug_cmd - - _G_last_arg_opt_p=false - func_truncate_cmd_result= - - set dummy "$@"; shift - - while test $# -gt 0; do - _G_opt=$1; shift - - test -n "$func_truncate_cmd_result" \ - && func_append func_truncate_cmd_result ' ' - func_append func_truncate_cmd_result "$_G_opt" - - func_len "x$func_truncate_cmd_result" - - case $_G_opt in - -*) _G_last_arg_opt_p=: ;; - *) $_G_last_arg_opt_p \ - || test "$min_cmd_len" -gt "$func_len_result" \ - || break - _G_last_arg_opt_p=false - ;; - esac - done - - test $# -gt 0 && func_append func_truncate_cmd_result "..." -} - - -# func_gitignore_entries FILE... -# ------------------------------ -# Strip blank and comment lines to leave significant entries. -func_gitignore_entries () -{ - $debug_cmd - - $SED -e '/^#/d' -e '/^$/d' "$@" -} - - -# func_insert_if_absent STR FILE... -# --------------------------------- -# If $STR is not already on a line by itself in $FILE, insert it, at the -# start. Entries are inserted at the start of the ignore list to ensure -# existing entries starting with ! are not overridden. Such entries -# support whilelisting exceptions after a more generic blacklist pattern. -# sorting the new contents of the file and replacing $FILE with the result. -func_insert_if_absent () -{ - $debug_cmd - - str=$1 - shift - - for file - do - test -f "$file" || touch "$file" - - duplicate_entries=`func_gitignore_entries "$file" |sort |uniq -d` - test -n "$duplicate_entries" \ - && func_error "duplicate entries in $file: " $duplicate_entries - - func_grep_q "^$str\$" "$file" \ - || func_verbose "inserting '$str' into '$file'" - - linesold=`func_gitignore_entries "$file" |wc -l` - linesnew=`{ $ECHO "$str"; cat "$file"; } \ - |func_gitignore_entries |sort -u |wc -l` - test "$linesold" -eq "$linesnew" \ - || { $SED "1i\\$nl$str$nl" "$file" >"$file"T && mv "$file"T "$file"; } \ - || func_permissions_error "$file" - done -} - - -# func_get_version APP -# -------------------- -# echo the version number (if any) of APP, which is looked up along your -# PATH. -func_get_version () -{ - $debug_cmd - - _G_app=$1 - - # Rather than uncomment the sed script in-situ, strip the comments - # programatically before passing the result to $SED for evaluation. - sed_get_version=`$ECHO '# extract version within line - s|.*[v ]\{1,\}\([0-9]\{1,\}\.[.a-z0-9-]*\).*|\1| - t done - - # extract version at start of line - s|^\([0-9]\{1,\}\.[.a-z0-9-]*\).*|\1| - t done - - d - - :done - # the following essentially does s|5.005|5.5| - s|\.0*\([1-9]\)|.\1|g - p - q' \ - |$SED '/^[ ]*#.*$/d'` - - func_tool_version_output $_G_app >/dev/null - _G_status=$? - - test 0 -ne "$_G_status" \ - || $_G_app --version 2>&1 |$SED -n "$sed_get_version" - - (exit $_G_status) -} - - -# func_check_tool APP -# ------------------- -# Search PATH for an executable at APP. -func_check_tool () -{ - $debug_cmd - - func_check_tool_result= - - case $1 in - *[\\/]*) - test -x "$1" && func_check_tool_result=$1 - ;; - *) - save_IFS=$IFS - IFS=${PATH_SEPARATOR-:} - for _G_check_tool_path in $PATH; do - IFS=$save_IFS - if test -x "$_G_check_tool_path/$1"; then - func_check_tool_result=$_G_check_tool_path/$1 - break - fi - done - IFS=$save_IFS - ;; - esac -} - - -# func_check_versions APP1 VER1 URL1 ...[APPN VERN URLN] -# ------------------------------------------------------ -func_check_versions () -{ - $debug_cmd - - func_check_versions_result=: - - while test $# -gt 0; do - _G_app=$1; shift - _G_reqver=$1; shift - _G_url=$1; shift - - # Diagnose bad buildreq formatting. - case $_G_url in - [a-z]*://*) ;; # looks like a url - *) func_fatal_error "\ -'$_G_url' from the buildreq table in -'bootstrap.conf' does not look like the URL for downloading -$_G_app. Please ensure that buildreq is a strict newline -delimited list of triples; 'program min-version url'." - ;; - esac - - # Honor $APP variables ($TAR, $AUTOCONF, etc.) - _G_appvar=`echo $_G_app |tr '[a-z]' '[A-Z]'` - test TAR = "$_G_appvar" && _G_appvar=AMTAR - eval "_G_app=\${$_G_appvar-$_G_app}" - - # Fail if no version specified, but the program can't be found. - if test x- = "x$_G_reqver"; then - func_check_tool $_G_app - if test -z "$func_check_tool_result"; then - func_error "Prerequisite '$_G_app' not not found. Please install it, or -'export $_G_appvar=/path/to/$_G_app'." - func_check_versions_result=false - else - func_verbose "found '$func_check_tool_result' for $_G_appvar." - fi - else - _G_instver=`func_get_version $_G_app` - - # Fail if --version didn't work. - if test -z "$_G_instver"; then - func_error "Prerequisite '$_G_app' not found. Please install it, or -'export $_G_appvar=/path/to/$_G_app'." - func_check_versions_result=false - - # Fail if a newer version than what we have is required. - else - func_verbose "found '$_G_app' version $_G_instver." - - case $_G_reqver in - =*) - # If $buildreq version starts with '=', version must - # match the installed program exactly. - test "x$_G_reqver" = "x=$_G_instver" || { - func_error "\ - '$_G_app' version == $_G_instver is too old - 'exactly $_G_app-$_G_reqver is required" - func_check_versions_result=false - } - ;; - *) - # Otherwise, anything that is not older is a match. - func_lt_ver "$_G_reqver" "$_G_instver" || { - func_error "\ - '$_G_app' version == $_G_instver is too old - '$_G_app' version >= $_G_reqver is required" - func_check_versions_result=false - } - ;; - esac - fi - fi - done -} - - -# func_cleanup_gnulib -# ------------------- -# Recursively delete everything below the path in the global variable -# GNULIB_PATH. -func_cleanup_gnulib () -{ - $debug_cmd - - _G_status=$? - $RM -fr "$gnulib_path" - exit $_G_status -} - - -# func_download_po_files SUBDIR DOMAIN -# ------------------------------------ -func_download_po_files () -{ - $debug_cmd - - func_echo "getting translations into $1 for $2..." - _G_cmd=`printf "$po_download_command_format" "$2" "$1"` - eval "$_G_cmd" -} - - -# func_update_po_files PO_DIR DOMAIN -# ---------------------------------- -# Mirror .po files to $po_dir/.reference and copy only the new -# or modified ones into $po_dir. Also update $po_dir/LINGUAS. -# Note po files that exist locally only are left in $po_dir but will -# not be included in LINGUAS and hence will not be distributed. -func_update_po_files () -{ - $debug_cmd - - # Directory containing primary .po files. - # Overwrite them only when we're sure a .po file is new. - _G_po_dir=$1 - _G_domain=$2 - - # Mirror *.po files into this dir. - # Usually contains *.s1 checksum files. - _G_ref_po_dir=$_G_po_dir/.reference - - test -d "$_G_ref_po_dir" || mkdir $_G_ref_po_dir || return - func_download_po_files $_G_ref_po_dir $_G_domain \ - && ls "$_G_ref_po_dir"/*.po 2>/dev/null \ - |$SED -e 's|.*/||' -e 's|\.po$||' > "$_G_po_dir/LINGUAS" || return - - # Find sha1sum, named gsha1sum on MacPorts, and shasum on MacOS 10.6+. - func_find_tool SHA1SUM sha1sum gsha1sum shasum sha1 - - test -n "$SHA1SUM" || func_fatal_error "\ -Please install GNU Coreutils, or 'export SHA1SUM=/path/to/sha1sum'." - - _G_langs=`cd $_G_ref_po_dir && echo *.po|$SED 's|\.po||g'` - test '*' = "$_G_langs" && _G_langs=x - for _G_po in $_G_langs; do - case $_G_po in x) continue;; esac - _G_new_po=$_G_ref_po_dir/$_G_po.po - _G_cksum_file=$_G_ref_po_dir/$_G_po.s1 - if ! test -f "$_G_cksum_file" || - ! test -f "$_G_po_dir/$_G_po.po" || - ! $SHA1SUM -c "$_G_cksum_file" \ - < "$_G_new_po" > /dev/null; then - echo "updated $_G_po_dir/$_G_po.po..." - cp "$_G_new_po" "$_G_po_dir/$_G_po.po" \ - && $SHA1SUM < "$_G_new_po" > "$_G_cksum_file" || return - fi - done -} - - - -## --------------- ## -## Option parsing. ## -## --------------- ## - -# Hook in the functions to make sure our own options are parsed during -# the option parsing loop. - -usage='$progpath [OPTION]...' - -# Short help message in response to '-h'. Add to this in 'bootstrap.conf' -# if you accept any additional options. -usage_message="Common Bootstrap Options: - -c, --copy copy files instead of creating symbolic links. - --debug enable verbose shell tracing - -n, --dry-run print commands rather than running them - -f, --force attempt to bootstrap even if the sources seem not - to have been checked out. - --gnulib-srcdir=DIRNAME - specify a local directory where gnulib sources - reside. Use this if you already have the gnulib - sources on your machine, and don't want to waste - your bandwidth downloading them again. Defaults to - \$GNULIB_SRCDIR. - --no-warnings equivalent to '-Wnone' - --skip-git do not fetch files from remote repositories - --skip-po do not download po files. - -v, --verbose verbosely report processing - --version print version information and exit - -W, --warnings=CATEGORY - report the warnings falling in CATEGORY [all] - -h, --help print short or long help message and exit -" - -# Additional text appended to 'usage_message' in response to '--help'. -long_help_message=$long_help_message" - 'recommend' show warnings about missing recommended packages - 'settings' show warnings about missing '$progname.conf' settings - 'upgrade' show warnings about out-dated files - -If the file '$progname.conf' exists in the same directory as this -script, its contents are read as shell variables to configure the -bootstrap. - -For build prerequisites, environment variables like \$AUTOCONF and -\$AMTAR are honored. - -Running without arguments will suffice in most cases. -" - -# Warning categories used by 'bootstrap', append others if you use them -# in your 'bootstrap.conf'. -warning_categories='recommend settings upgrade' - - -# bootstrap_options_prep [ARG]... -# ------------------------------- -# Preparation for options parsed by Bootstrap. -bootstrap_options_prep () -{ - $debug_cmd - - # Option defaults: - opt_copy=${copy-'false'} - opt_dry_run=false - opt_force=false - opt_gnulib_srcdir=$GNULIB_SRCDIR - opt_skip_git=false - opt_skip_po=false - - # Pass back the list of options we consumed. - func_quote_for_eval ${1+"$@"} - bootstrap_options_prep_result=$func_quote_for_eval_result -} -func_add_hook func_options_prep bootstrap_options_prep - - -# bootstrap_parse_options [ARG]... -# -------------------------------- -# Provide handling for Bootstrap specific options. -bootstrap_parse_options () -{ - $debug_cmd - - # Perform our own loop to consume as many options as possible in - # each iteration. - while test $# -gt 0; do - _G_opt=$1 - shift - case $_G_opt in - --dry-run|--dryrun|-n) - opt_dry_run=: ;; - --copy|-c) opt_copy=: ;; - --force|-f) opt_force=: ;; - - --gnulib-srcdir) - test $# = 0 && func_missing_arg $_G_opt && break - opt_gnulib_srcdir=$1 - shift - ;; - - --skip-git|--no-git) - opt_skip_git=: - ;; - - --skip-po|--no-po) - opt_skip_po=: - ;; - - # Separate non-argument short options: - -c*|-f*|-n*) - func_split_short_opt "$_G_opt" - set dummy "$func_split_short_opt_name" \ - "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; - esac - done - - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - bootstrap_parse_options_result=$func_quote_for_eval_result -} -func_add_hook func_parse_options bootstrap_parse_options - - -# bootstrap_validate_options [ARG]... -# ----------------------------------- -# Perform any sanity checks on option settings and/or unconsumed -# arguments. -bootstrap_validate_options () -{ - $debug_cmd - - # Validate options. - test $# -gt 0 \ - && func_fatal_help "too many arguments" - - # Pass back the (empty) list of unconsumed options. - func_quote_for_eval ${1+"$@"} - bootstrap_validate_options_result=$func_quote_for_eval_result -} -func_add_hook func_validate_options bootstrap_validate_options - - -## -------------------------------------------------- ## -## Source package customisations in 'bootstrap.conf'. ## -## -------------------------------------------------- ## - -# Override the default configuration, if necessary. -# Make sure that bootstrap.conf is sourced from the current directory -# if we were invoked as "sh bootstrap". -case $0 in - */*) test -r "$0.conf" && . "$0.conf" ;; - *) test -r "$0.conf" && . ./"$0.conf" ;; -esac - - -## ------------------------------- ## -## Actually perform the bootstrap. ## -## ------------------------------- ## - -func_bootstrap ${1+"$@"} - -# The End. -exit ${exit_status-$EXIT_SUCCESS} - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "500/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: diff --git a/bootstrap.conf b/bootstrap.conf deleted file mode 100644 index b2326348..00000000 --- a/bootstrap.conf +++ /dev/null @@ -1,160 +0,0 @@ -# bootstrap.conf (GNU M4) version 2017-01-03 -# Written by Gary V. Vaughan, 2010 - -# Copyright (C) 2010, 2013-2014, 2017 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 . - - -## -------------- ## -## Configuration. ## -## -------------- ## - -copyright_holder="Free Software Foundation, Inc." - -# List of programs (and minimum versions) required to bootstrap, maintain -# and release Libtool. -buildreq=' - help2man 1.29 http://www.gnu.org/s/help2man - makeinfo 4.13 http://www.gnu.org/s/texinfo - xz - http://tukaani.org/xz -' - -# Instructions on how to install packages in $buildreq. -buildreq_readme=HACKING - -# A file only visible in a vcs working directory. -checkout_only_file=HACKING - -# Local gnulib submodule path. -gnulib_path=build-aux/gnulib - -# Additional gnulib-tool options to use. -gnulib_tool_options=$gnulib_tool_options' - --libtool -' - -# gnulib_modules must remain empty in order to get --update style -# gnulib-tool invocations, so we add the bootstrap components here. -gnulib_non_module_files=$gnulib_non_module_files" - build-aux/bootstrap.in - build-aux/extract-trace - build-aux/funclib.sh - build-aux/inline-source - build-aux/options-parser" - -# List dependencies here too; we don't extract them, otherwise dependent -# modules could end up being imported to src/ *and* gnu/! -src_modules=' -assure -getopt-gnu -getopt-posix -version-etc-fsf -version-etc -xstrtol -' - -# What ignore files to maintain. -vc_ignore=".gitignore" - - -## --------------- ## -## Hook functions. ## -## --------------- ## - - -# m4_precopy_git_version_gen -# -------------------------- -# Autopoint gets confused if git-version-gen is missing. -m4_precopy_git_version_gen () -{ - $debug_cmd - - $require_build_aux - - func_gnulib_tool_copy_file build-aux/git-version-gen $build_aux/git-version-gen -} -func_add_hook func_prep m4_precopy_git_version_gen - - -# m4_install_texinfo_diff_driver -# ------------------------------ -# Help git to do a better job of merging texinfo files. -m4_install_texinfo_diff_driver () -{ - $debug_cmd - - $require_git - - test true = "$GIT" || { - if $GIT config diff.texinfo.funcname >/dev/null ; then - : - else - func_echo "initializing git texinfo diff driver" - git config diff.texinfo.funcname '^@node[ \t][ \t]*\\([^,][^,]*\\)' - fi - } -} -func_add_hook func_prep m4_install_texinfo_diff_driver - - -# m4_copy_src_modules -# ------------------- -# Copy $src_modules from gnulib to src directory. -m4_copy_src_modules () -{ - $debug_cmd - - $require_gnulib_tool - - test true = "$gnulib_tool" || { - $require_macro_dir - - for file in `$gnulib_tool --extract-filelist $src_modules | sort -u` - do - maybe_exit_cmd=: - - func_basename $file - dest=$func_basename_result - - case $file in - lib/*) dest=src/$dest ;; - m4/*) dest=$macro_dir/$dest ;; - *) func_error "$file: unknown file" - maybe_exit_cmd="exit $EXIT_FAILURE" - dest= ;; - esac - - # Be sure to show all copying errors before bailing out - if test -n "$dest"; then - func_gnulib_tool_copy_file "$file" "$dest" - fi - done - - $maybe_exit_cmd - } -} -func_add_hook func_gnulib_tool m4_copy_src_modules - - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "# bootstrap.conf (GNU M4) version " -# time-stamp-format: "%:y-%02m-%02d" -# time-stamp-end: "$" -# End: diff --git a/build-aux/gl/build-aux/bootstrap.in b/build-aux/gl/build-aux/bootstrap.in deleted file mode 100755 index 4cc7362b..00000000 --- a/build-aux/gl/build-aux/bootstrap.in +++ /dev/null @@ -1,2769 +0,0 @@ -#! /bin/sh - -# Bootstrap an Autotooled package from checked-out sources. -# Written by Gary V. Vaughan, 2010 - -# Copyright (C) 2010-2014, 2017 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Originally written by Paul Eggert. The canonical version of this -# script is maintained as build-aux/bootstrap in gnulib, however, to -# be useful to your project, you should place a copy of it under -# version control in the top-level directory of your project. The -# intent is that all customization can be done with a bootstrap.conf -# file also maintained in your version control; gnulib comes with a -# template build-aux/bootstrap.conf to get you started. - -# Please report bugs or propose patches to bug-gnulib@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# Most GNUish projects do not keep all of the generated Autotool -# files under version control, but running all of the right tools -# with the right arguments, in the correct order to regenerate -# all of those files in readiness for configuration and building -# can be surprisingly involved! Many projects have a 'bootstrap' -# script under version control to invoke Autotools and perform -# other assorted book-keeping with version numbers and the like. -# -# This bootstrap script aims to probe the configure.ac and top -# Makefile.am of your project to automatically determine what -# the correct ordering and arguments are and then run the tools for -# you. In order to use it, you can generate an initial standalone -# script with: -# -# gl/build-aux/inline-source gl/build-aux/bootstrap.in > bootstrap -# -# You should then store than script in version control for other -# developers in you project. It will give you instructions about -# how to keep it up to date if the sources change. -# -# See gl/doc/bootstrap.texi for documentation on how to write -# a bootstrap.conf to customize it for your project's -# idiosyncracies. - - -## ================================================================== ## -## ## -## DO NOT EDIT THIS FILE, CUSTOMIZE IT USING A BOOTSTRAP.CONF ## -## ## -## ================================================================== ## - -## ------------------------------- ## -## User overridable command paths. ## -## ------------------------------- ## - -# All uppercase denotes values stored in the environment. These -# variables should generally be overridden by the user - however, we do -# set them to 'true' in some parts of this script to prevent them being -# called at the wrong time by other tools that we call ('autoreconf', -# for example). -# -# We also allow 'LIBTOOLIZE', 'M4', 'SHA1SUM' and some others to be -# overridden, and export the result for child processes, but they are -# handled by the function 'func_find_tool' and not defaulted in this -# section. - -: ${ACLOCAL="aclocal"} -: ${AUTOCONF="autoconf"} -: ${AUTOHEADER="autoheader"} -: ${AUTOM4TE="autom4te"} -: ${AUTOHEADER="autoheader"} -: ${AUTOMAKE="automake"} -: ${AUTOPOINT="autopoint"} -: ${AUTORECONF="autoreconf"} -: ${CMP="cmp"} -: ${CONFIG_SHELL="/bin/sh"} -: ${DIFF="diff"} -: ${GIT="git"} -: ${LN_S="ln -s"} -: ${RM="rm"} - -export ACLOCAL -export AUTOCONF -export AUTOHEADER -export AUTOM4TE -export AUTOHEADER -export AUTOMAKE -export AUTOPOINT -export AUTORECONF -export CONFIG_SHELL - - -## -------------- ## -## Configuration. ## -## -------------- ## - -# A newline delimited list of triples of programs (that respond to -# --version), the minimum version numbers required (or just '-' in the -# version field if any version will be sufficient) and homepage URLs -# to help locate missing packages. -buildreq= - -# Name of a file containing instructions on installing missing packages -# required in 'buildreq'. -buildreq_readme=README-hacking - -# These are extracted from AC_INIT in configure.ac, though you can -# override those values in 'bootstrap.conf' if you prefer. -build_aux= -macro_dir= -package= -package_name= -package_version= -package_bugreport= - -# These are extracted from 'gnulib-cache.m4', or else fall-back -# automatically on the gnulib defaults; unless you set the values -# manually in 'bootstrap.conf'. -doc_base= -gnulib_mk= -gnulib_name= -local_gl_dir= -source_base= -tests_base= - -# The list of gnulib modules required at 'gnulib-tool' time. If you -# check 'gnulib-cache.m4' into your repository, then this list will be -# extracted automatically. -gnulib_modules= - -# Extra gnulib files that are not in modules, which override files of -# the same name installed by other bootstrap tools. -gnulib_non_module_files=" - build-aux/compile - build-aux/install-sh - build-aux/mdate-sh - build-aux/texinfo.tex - build-aux/depcomp - build-aux/config.guess - build-aux/config.sub - doc/INSTALL -" - -# Relative path to the local gnulib submodule, and url to the upstream -# git repository. If you have a gnulib entry in your .gitmodules file, -# these values are ignored. -gnulib_path= -gnulib_url= - -# Additional gnulib-tool options to use. -gnulib_tool_options=" - --no-changelog -" - -# bootstrap removes any macro-files that are not included by aclocal.m4, -# except for files listed in this variable that are always kept. -gnulib_precious=" - gnulib-tool.m4 -" - -# When truncating long commands for display, always allow at least this -# many characters before truncating. -min_cmd_len=160 - -# The command to download all .po files for a specified domain into -# a specified directory. Fill in the first %s is the domain name, and -# the second with the destination directory. Use rsync's -L and -r -# options because the latest/%s directory and the .po files within are -# all symlinks. -po_download_command_format=\ -"rsync --delete --exclude '*.s1' -Lrtvz \ -'translationproject.org::tp/latest/%s/' '%s'" - -# Other locale categories that need message catalogs. -extra_locale_categories= - -# Additional xgettext options to use. Gnulib might provide you with an -# extensive list of additional options to append to this, but gettext -# 0.16.1 and newer appends them automaticaly, so you can safely ignore -# the complaints from 'gnulib-tool' if your $configure_ac states: -# -# AM_GNU_GETTEXT_VERSION([0.16.1]) -xgettext_options=" - --flag=_:1:pass-c-format - --flag=N_:1:pass-c-format -" - -# Package copyright holder for gettext files. Defaults to FSF if unset. -copyright_holder= - -# File that should exist in the top directory of a checked out hierarchy, -# but not in a distribution tarball. -checkout_only_file= - -# Whether to use copies instead of symlinks by default (if set to true, -# the --copy option has no effect). -copy=false - -# Set this to ".cvsignore .gitignore" in 'bootstrap.conf' if you want -# those files to be generated in directories like 'lib/', 'm4/', and 'po/', -# or set it to "auto" to make this script select what to use based -# on what version control system (if any) is used in the source directory. -# Or set it to "none" to ignore VCS ignore files entirely. Default is -# "auto". -vc_ignore= - - -## ------------------- ## -## External Libraries. ## -## ------------------- ## - -# Source required external libraries: -. `echo "$0" |${SED-sed} 's|[^/]*$||'`"funclib.sh" -. `echo "$0" |${SED-sed} 's|[^/]*$||'`"options-parser" -. `echo "$0" |${SED-sed} 's|[^/]*$||'`"extract-trace" - -# Set a version string for *this* script. -scriptversion=2014-11-04.13; # UTC - - -## ------------------- ## -## Hookable functions. ## -## ------------------- ## - -# After 'bootstrap.conf' has been sourced, execution proceeds by calling -# 'func_bootstrap'. Wherever a function is decorated with -# 'func_hookable func_name', you will find a matching 'func_run_hooks -# func_name', which executes all functions added with 'func_add_hook -# func_name my_func'. -# -# You might notice that many of these functions begin with a series of -# '$require_foo' lines. See the docu-comments at the start of the -# 'Resource management' section for a description of what these are. - - -# func_bootstrap [ARG]... -# ----------------------- -# All the functions called inside func_bootstrap are hookable. See the -# the individual implementations for details. -func_bootstrap () -{ - $debug_cmd - - # Save the current positional parameters to prevent them being - # corrupted by calls to 'set' in 'func_init'. - func_quote_for_eval ${1+"$@"} - _G_saved_positional_parameters=$func_quote_for_eval_result - - # Initialisation. - func_init - - # Option processing. - eval func_options "$_G_saved_positional_parameters" - - # Post-option preparation. - func_prep - - # Reconfigure the package. - func_reconfigure - - # Ensure .version is up-to-date. - func_update_dotversion - - # Finalisation. - func_fini -} - - -# func_init -# --------- -# Any early initialisations can be hooked to this function. Consider -# whether you can hook onto 'func_prep' instead, because if you hook -# any slow to execute code in here, it will also add to the time before -# './bootstrap --version' can respond. -func_hookable func_init -func_init () -{ - $debug_cmd - - func_run_hooks func_init -} - - -# func_prep -# --------- -# Function to perform preparation for remaining bootstrap process. If -# your hooked code relies on the outcome of 'func_options' hook it here -# rather than to 'func_init'. -# -# All the functions called inside func_prep are hookable. See the -# individual implementations for details. -func_hookable func_prep -func_prep () -{ - $debug_cmd - - $require_buildtools_uptodate - $require_checkout_only_file - - $require_gnulib_merge_changelog - - # Report the results of SED and GREP searches from funclib.sh. - func_verbose "GREP='$GREP'" - func_verbose "SED='$SED'" - - # fetch update files from the translation project - func_update_translations - - func_run_hooks func_prep -} - - -# func_update_translations -# ------------------------ -# Update package po files and translations. -func_hookable func_update_translations -func_update_translations () -{ - $debug_cmd - - $opt_skip_po || { - test -d po && { - $require_package - - func_update_po_files po $package || exit $? - } - - func_run_hooks func_update_translations - } -} - - -# func_reconfigure -# ---------------- -# Reconfigure the current package by running the appropriate autotools in a -# suitable order. -func_hookable func_reconfigure -func_reconfigure () -{ - $debug_cmd - - $require_automake_options - - # Automake (without 'foreign' option) requires that README exists. - case " $automake_options " in - " foreign ") ;; - *) func_ensure_README ;; - esac - - # Ensure ChangeLog presence. - if test -n "$gnulib_modules"; then - func_ifcontains "$gnulib_modules" gitlog-to-changelog \ - func_ensure_changelog - else - $require_gnulib_cache - if $SED -n '/^gl_MODULES(\[/,/^])$/p' $gnulib_cache 2>/dev/null | - func_grep_q gitlog-to-changelog - then - func_ensure_changelog - fi - fi - - # Released 'autopoint' has the tendency to install macros that have - # been obsoleted in current 'gnulib', so run this before 'gnulib-tool'. - func_autopoint - - # Autoreconf runs 'aclocal' before 'libtoolize', which causes spurious - # warnings if the initial 'aclocal' is confused by the libtoolized - # (or worse: out-of-date) macro directory. - func_libtoolize - - # If you need to do anything after 'gnulib-tool' is done, but before - # 'autoreconf' runs, you don't need to override this whole function, - # because 'func_gnulib_tool' is hookable. - func_gnulib_tool - - func_autoreconf - - func_run_hooks func_reconfigure -} - - -# func_gnulib_tool -# ---------------- -# Run 'gnulib-tool' to fetch gnulib modules into the current package. -# -# It's assumed that since you are using gnulib's 'bootstrap' script, -# you're also using gnulib elsewhere in your package. If not, then -# you can replace this function in 'bootstrap.conf' with: -# -# func_gnulib_tool () { :; } -# -# (although the function returns immediately if $gnulib_tool is set to -# true in any case). -func_hookable func_gnulib_tool -func_gnulib_tool () -{ - $debug_cmd - - $require_gnulib_tool - $require_libtoolize - - test true = "$gnulib_tool" || { - # bootstrap.conf written for gnulib bootstrap expects - # gnulib_tool_option_extras to which --no-changelog is appended, - # but libtool bootstrap expects you to append to gnulib_tool_options - # so that you can override the --no-changelog default: make sure we - # support both styles so users can migrate between them easily. - gnulib_tool_all_options="$gnulib_tool_options $gnulib_tool_option_extras" - - if test -n "$gnulib_modules"; then - $require_gnulib_cache - $require_gnulib_tool_base_options - - gnulib_mode=--import - - # Try not to pick up any stale values from 'gnulib-cache.m4'. - rm -f "$gnulib_cache" - - test -n "$gnulib_tool_base_options" \ - && func_append_uniq gnulib_tool_all_options " $gnulib_tool_base_options" - test -n "$gnulib_mk" \ - && func_append_uniq gnulib_tool_all_options " --makefile-name=$gnulib_mk" - test -n "$tests_base" && { - func_append_uniq gnulib_tool_all_options " --tests-base=$tests_base" - func_append_uniq gnulib_tool_all_options " --with-tests" - } - else - - # 'gnulib_modules' and others are cached in 'gnulib-cache.m4': - # Use 'gnulib --update' to fetch gnulib modules. - gnulib_mode=--update - fi - - # Add a sensible default libtool option to gnulib_tool_options. - # The embedded echo is to squash whitespace before globbing. - case `echo " "$gnulib_tool_all_options" "` in - *" --no-libtool "*|*" --libtool "*) ;; - *) if test true = "$LIBTOOLIZE"; then - func_append_uniq gnulib_tool_all_options " --no-libtool" - else - func_append_uniq gnulib_tool_all_options " --libtool" - fi - ;; - esac - - $opt_copy || func_append_uniq gnulib_tool_all_options " --symlink" - - func_append_uniq gnulib_tool_all_options " $gnulib_mode" - func_append gnulib_tool_all_options " $gnulib_modules" - - # The embedded echo is to squash whitespace before display. - gnulib_cmd=`echo $gnulib_tool $gnulib_tool_all_options` - - func_show_eval "$gnulib_cmd" 'exit $?' - - # Use 'gnulib-tool --copy-file' to install non-module files. - func_install_gnulib_non_module_files - } - - func_run_hooks func_gnulib_tool -} - - -# func_fini -# --------- -# Function to perform all finalisation for the bootstrap process. -func_hookable func_fini -func_fini () -{ - $debug_cmd - - func_gettext_configuration - func_clean_dangling_symlinks - func_clean_unused_macros - func_skip_po_recommendation - - func_run_hooks func_fini - - $require_bootstrap_uptodate - - func_echo "Done. Now you can run './configure'." -} - - -# func_gettext_configuration -# -------------------------- -# Edit configuration values into po/Makevars. -func_hookable func_gettext_configuration -func_gettext_configuration () -{ - $debug_cmd - - $require_autopoint - - test true = "$AUTOPOINT" || { - $require_copyright_holder - $require_extra_locale_categories - $require_package_bugreport - - # Escape xgettext options for sed Makevars generation below. - # We have to delete blank lines in a separate script so that we don't - # append \\\ to the penultimate line, and then delete the last empty - # line, which messes up the variable substitution later in this - # function. Note that adding a literal \\\ requires double escaping - # here, once for the execution subshell, and again for the assignment, - # which is why there are actually 12 (!!) backslashes in the script. - _G_xgettext_options=`echo "$xgettext_options$nl" |$SED '/^$/d' |$SED ' - $b - s|$| \\\\\\\\\\\\|'` - - # Create gettext configuration. - func_echo "Creating po/Makevars from po/Makevars.template ..." - $RM -f po/Makevars - $SED ' - /^EXTRA_LOCALE_CATEGORIES *=/s|=.*|= '"$extra_locale_categories"'| - /^COPYRIGHT_HOLDER *=/s|=.*|= '"$copyright_holder"'| - /^MSGID_BUGS_ADDRESS *=/s|=.*|= '"$package_bugreport"'| - /^XGETTEXT_OPTIONS *=/{ - s|$| \\| - a\ - '"$_G_xgettext_options"' \\\ - $${end_of_xgettext_options+} - } - ' po/Makevars.template >po/Makevars || exit 1 - } - - func_run_hooks func_gettext_configuration -} - - - -## --------------- ## -## Core functions. ## -## --------------- ## - -# This section contains the main functions called from the 'Hookable -# functions' (shown above), and are the ones you're most likely -# to want to replace with your own implementations in 'bootstrap.conf'. - - -# func_autopoint -# -------------- -# If this package uses gettext, then run 'autopoint'. -func_autopoint () -{ - $debug_cmd - - $require_autopoint - - test true = "$AUTOPOINT" \ - || func_show_eval "$AUTOPOINT --force" 'exit $?' -} - - -# func_libtoolize -# --------------- -# If this package uses libtool, then run 'libtoolize'. -func_libtoolize () -{ - $debug_cmd - - $require_libtoolize - - test true = "$LIBTOOLIZE" || { - _G_libtoolize_options= - $opt_copy && func_append _G_libtoolize_options " --copy" - $opt_force && func_append _G_libtoolize_options " --force" - $opt_verbose || func_append _G_libtoolize_options " --quiet" - func_show_eval "$LIBTOOLIZE$_G_libtoolize_options" 'exit $?' - } -} - - -# func_gnulib_tool_copy_file SRC DEST -# ----------------------------------- -# Copy SRC, a path relative to the gnulib sub-tree, to DEST, a path -# relative to the top-level source directory using gnulib-tool so that -# any patches or replacements in $local_gl_dir are applied. -func_gnulib_tool_copy_file () -{ - $debug_cmd - - $require_gnulib_tool - $require_patch - - if test true = "$gnulib_tool"; then - # If gnulib-tool is not available (e.g. bootstrapping in a - # distribution tarball), make sure that at least we have some - # version of the required file already in place. - test -f "$2" || func_fatal_error "\ -Can't find, copy or download '$2', a required -gnulib supplied file, please provide the location of a -complete 'gnulib' tree by setting 'gnulib_path' in your -'bootstrap.conf' or with the '--gnulib-srcdir' option - -or else specify the location of your 'git' binary by -setting 'GIT' in the environment so that a fresh -'gnulib' submodule can be cloned." - else - $require_gnulib_copy_cmd - - $gnulib_copy_cmd $1 $2 2>/dev/null || { - $require_gnulib_path - - func_error "'$gnulib_path/$1' does not exist" - return 1 - } - fi -} - - -# func_install_gnulib_non_module_files -# ------------------------------------ -# Get additional non-module files from gnulib, overriding existing files. -func_install_gnulib_non_module_files () -{ - $debug_cmd - - $require_build_aux - $require_gnulib_tool - - test -n "$gnulib_non_module_files" && { - maybe_exit_cmd=: - - for file in $gnulib_non_module_files; do - case $file in - */COPYING*) dest=COPYING;; - */INSTALL) dest=INSTALL;; - build-aux/missing) dest= - func_warning settings "\ -Please remove build-aux/missing from gnulib_module_files in -'bootstrap.conf', as it may clash with Automake's version." - ;; - build-aux/*) dest=$build_aux/`expr "$file" : 'build-aux/\(.*\)'`;; - *) dest=$file;; - esac - - # Be sure to show all copying errors before bailing out - test -z "$dest" \ - || func_gnulib_tool_copy_file "$file" "$dest" \ - || maybe_exit_cmd="exit $EXIT_FAILURE" - done - - $maybe_exit_cmd - } -} - - -# func_ensure_changelog -# --------------------- -# Even with 'gitlog-to-changelog' generated ChangeLogs, automake -# will not run to completion with no ChangeLog file. -func_ensure_changelog () -{ - $debug_cmd - - test -f ChangeLog && mv -f ChangeLog ChangeLog~ - - cat >ChangeLog <<'EOT' -## ---------------------- ## -## DO NOT EDIT THIS FILE! ## -## ---------------------- ## - -ChangeLog is generated by gitlog-to-changelog. -EOT - - _G_message="creating dummy 'ChangeLog'" - test -f ChangeLog~ \ - && func_append _G_message ' (backup in ChangeLog~)' - func_verbose "$_G_message" - - return 0 -} - - -# func_ensure_README -# ------------------ -# Without AM_INIT_AUTOMAKE([foreign]), automake will not run to -# completion with no README file, even though README.md or README.txt -# is often preferable. -func_ensure_README () -{ - $debug_cmd - - test -f README || { - _G_README= - for _G_readme in README.txt README.md README.rst; do - test -f "$_G_readme" && break - done - - test -f "$_G_readme" && $LN_S $_G_readme README - func_verbose "$LN_S $_G_readme README" - } - - return 0 -} - - -# func_autoreconf [SUBDIR] -# ------------------------ -# Being careful not to re-run 'autopoint' or 'libtoolize', and not to -# try to run 'autopoint', 'libtoolize' or 'autoheader' on packages that -# don't use them, defer to 'autoreconf' for execution of the remaining -# autotools to bootstrap this package. -# -# Projects with multiple trees to reconfigure can hook another call to -# this function onto func_reconfigure: -# -# my_autoreconf_foo () -# { -# func_autoreconf foo -# } -# func_add_hook func_reconfigure my_autoreconf_foo -func_autoreconf () -{ - $debug_cmd - - $require_autoheader - $require_build_aux # automake and others put files in here - $require_macro_dir # aclocal and others put files in here - - # We ran these manually already, and autoreconf won't exec ':' - save_AUTOPOINT=$AUTOPOINT; AUTOPOINT=true - save_LIBTOOLIZE=$LIBTOOLIZE; LIBTOOLIZE=true - - _G_autoreconf_options= - $opt_copy || func_append _G_autoreconf_options " --symlink" - $opt_force && func_append _G_autoreconf_options " --force" - $opt_verbose && func_append _G_autoreconf_options " --verbose" - func_show_eval "$AUTORECONF$_G_autoreconf_options --install${1+ $1}" 'exit $?' - - AUTOPOINT=$save_AUTOPOINT - LIBTOOLIZE=$save_LIBTOOLIZE -} - - -# func_check_configuration VARNAME [CONFIGURE_MACRO] -# -------------------------------------------------- -# Exit with a suitable diagnostic for an important configuration change -# that needs to be made before bootstrap can run correctly. -func_check_configuration () -{ - $debug_cmd - - $require_configure_ac - - eval 'test -n "$'$1'"' || { - _G_error_msg="please set '$1' in 'bootstrap.conf'" - if test -n "$configure_ac" && test -n "$2"; then - func_append _G_error_msg " -or add the following (or similar) to your '$configure_ac': -$2" - fi - - func_fatal_error "$_G_error_msg" - } -} - - -# func_clean_dangling_symlinks -# ---------------------------- -# Remove any dangling symlink matching "*.m4" or "*.[ch]" in some -# gnulib-populated directories. Such .m4 files would cause aclocal to -# fail. The following requires GNU find 4.2.3 or newer. Considering -# the usual portability constraints of this script, that may seem a very -# demanding requirement, but it should be ok. Ignore any failure, -# which is fine, since this is only a convenience to help developers -# avoid the relatively unusual case where a symlinked-to .m4 file is -# git-removed from gnulib between successive runs of this script. -func_clean_dangling_symlinks () -{ - $debug_cmd - - $require_macro_dir - $require_source_base - - func_verbose "cleaning dangling symlinks" - - find "$macro_dir" "$source_base" \ - -depth \( -name '*.m4' -o -name '*.[ch]' \) \ - -type l -xtype l -delete > /dev/null 2>&1 -} - - -# func_clean_unused_macros -# ------------------------ -# Autopoint can result in over-zealously adding macros into $macro_dir -# even though they are not actually used, for example tests to help -# build the 'intl' directory even though you have specified -# 'AM_GNU_GETTEXT([external])' in your configure.ac. This function -# looks removes any macro files that can be found in gnulib, but -# are not 'm4_include'd by 'aclocal.m4'. -func_clean_unused_macros () -{ - $debug_cmd - - $require_gnulib_path - $require_macro_dir - - test -n "$gnulib_path" && test -f aclocal.m4 && { - aclocal_m4s=`find . -name aclocal.m4 -print` - - # We use 'ls|grep' instead of 'ls *.m4' to avoid exceeding - # command line length limits in some shells. - for file in `cd "$macro_dir" && ls -1 |$GREP '\.m4$'`; do - - # Remove a macro file when aclocal.m4 does not m4_include it... - func_grep_q 'm4_include([[]'$macro_dir/$file'])' $aclocal_m4s \ - || test ! -f "$gnulib_path/m4/$file" || { - - # ...and there is an identical file in gnulib... - if func_cmp_s "$gnulib_path/m4/$file" "$macro_dir/$file"; then - - # ...and it's not in the precious list ('echo' is needed - # here to squash whitespace for the match expression). - case " "`echo $gnulib_precious`" " in - *" $file "*) ;; - *) rm -f "$macro_dir/$file" - func_verbose \ - "removing unused gnulib file '$macro_dir/$file'" - esac - fi - } - done - } -} - - -# func_skip_po_recommendation -# --------------------------- -# If there is a po directory, and '--skip-po' wasn't passed, let the -# user know that they can use '--skip-po' on subsequent invocations. -func_skip_po_recommendation () -{ - $debug_cmd - - test ! -d po \ - || $opt_skip_po \ - || func_warning recommend "\ -If your pofiles are up-to-date, you can rerun bootstrap -as '$progname --skip-po' to avoid redownloading." -} - - -# func_update_dotversion -# ---------------------- -# Even with 'gitlog-to-changelog' generated ChangeLogs, automake -# will not run to completion with no ChangeLog file. -func_update_dotversion () -{ - $debug_cmd - - test -f "$build_aux/git-version-gen" && { - _G_message="updating .version" - test -f .version && { - mv .version .version~ - func_append _G_message " (backup in .version~)" - } - func_verbose "updating .version" - - $build_aux/git-version-gen dummy-arg > .version - } -} - - - -## -------------------- ## -## Resource management. ## -## -------------------- ## - -# This section contains definitions for functions that each ensure a -# particular resource (a file, or a non-empty configuration variable for -# example) is available, and if appropriate to extract default values -# from pertinent package files. Where a variable already has a non- -# empty value (as set by the package's 'bootstrap.conf'), that value is -# used in preference to deriving the default. Call them using their -# associated 'require_*' variable to ensure that they are executed, at -# most, once. - - -# require_checkout_only_file -# -------------------------- -# Bail out if this package only bootstraps properly from a repository -# checkout. -require_checkout_only_file=func_require_checkout_only_file -func_require_checkout_only_file () -{ - $debug_cmd - - $opt_force || { - test -n "$checkout_only_file" && test ! -f "$checkout_only_file" \ - && func_fatal_error "\ -Bootstrapping from a non-checked-out distribution is risky. -If you wish to bootstrap anyway, use the '--force' option." - } - - require_checkout_only_file=: -} - - -# require_aclocal_amflags -# ----------------------- -# Ensure '$aclocal_amflags' has a sensible default, extracted from -# 'Makefile.am' if necessary. -require_aclocal_amflags=func_require_aclocal_amflags -func_require_aclocal_amflags () -{ - $debug_cmd - - $require_makefile_am - - _G_sed_extract_aclocal_amflags='s|#.*$|| - /^[ ]*ACLOCAL_AMFLAGS[ ]*=/ { - s|^.*=[ ]*\(.*\)|aclocal_amflags="\1"| - p - }' - - _G_aclocal_flags_cmd=`$SED -n "$_G_sed_extract_aclocal_amflags" \ - "$makefile_am"` - eval "$_G_aclocal_flags_cmd" - - func_verbose "ACLOCAL_AMFLAGS='$aclocal_amflags'" - - require_aclocal_amflags=: -} - - -# require_autoheader -# ------------------ -# Skip autoheader if it's not needed. -require_autoheader=func_require_autoheader -func_require_autoheader () -{ - $debug_cmd - - test true = "$AUTOHEADER" || { - func_extract_trace AC_CONFIG_HEADERS - test -n "$func_extract_trace_result" \ - || func_extract_trace AC_CONFIG_HEADER - - test -n "$func_extract_trace_result" || { - AUTOHEADER=true - - func_verbose "export AUTOHEADER='$AUTOHEADER'" - - # Make sure the search result is visible to subshells - export AUTOHEADER - } - } - - require_autoheader=: -} - - -# require_automake_options -# ------------------------ -# Extract options from AM_AUTOMAKE_INIT. -require_automake_options=func_require_automake_options -func_require_automake_options () -{ - $debug_cmd - - func_extract_trace AM_INIT_AUTOMAKE - automake_options=$func_extract_trace_result - - require_automake_options=: -} - - -# require_autopoint -# ----------------- -# Skip autopoint if it's not needed. -require_autopoint=func_require_autopoint -func_require_autopoint () -{ - $debug_cmd - - test true = "$AUTOPOINT" || { - func_extract_trace AM_GNU_GETTEXT_VERSION - - test -n "$func_extract_trace_result" || { - AUTOPOINT=true - - func_verbose "export AUTOPOINT='$AUTOPOINT'" - - # Make sure the search result is visible to subshells - export AUTOPOINT - } - } - - require_autopoint=: -} - - -# require_bootstrap_uptodate -# -------------------------- -# Complain if the version of bootstrap in the gnulib directory differs -# from the one we are running. -require_bootstrap_uptodate=func_require_bootstrap_uptodate -func_require_bootstrap_uptodate () -{ - $debug_cmd - - $require_build_aux - - _G_bootstrap_sources=" - $build_aux/bootstrap.in - $build_aux/extract-trace - $build_aux/funclib.sh - $build_aux/options-parser - " - - _G_missing_bootstrap_sources=false - for _G_src in $_G_bootstrap_sources; do - test -f "$_G_src" || _G_missing_bootstrap_sources=: - done - - if $_G_missing_bootstrap_sources; then - func_warning upgrade "\ -Please add bootstrap to your gnulib_modules list in -'bootstrap.conf', so that I can tell you when there are -updates available." - else - rm -f bootstrap.new - $build_aux/inline-source $build_aux/bootstrap.in > bootstrap.new - - if func_cmp_s "$progpath" bootstrap.new; then - rm -f bootstrap.new - func_verbose "bootstrap script up to date" - else - chmod 555 bootstrap.new - func_warning upgrade "\ -An updated bootstrap script has been generated for you in -'bootstrap.new'. After you've verified that you want -the changes, you can update with: - mv -f bootstrap.new $progname - ./$progname - -Or you can disable this check permanently by adding the -following to 'bootstrap.conf': - require_bootstrap_uptodate=:" - fi - fi - - require_bootstrap_uptodate=: -} - - -# require_build_aux -# ----------------- -# Ensure that '$build_aux' is set, and if it doesn't already point to an -# existing directory, create one. -require_build_aux=func_require_build_aux -func_require_build_aux () -{ - $debug_cmd - - test -n "$build_aux" || { - func_extract_trace_first AC_CONFIG_AUX_DIR - build_aux=$func_extract_trace_first_result - func_check_configuration build_aux \ - "AC_CONFIG_AUX_DIR([name of a directory for build scripts])" - - func_verbose "build_aux='$build_aux'" - } - - $require_vc_ignore_files - - # If the build_aux directory doesn't exist, create it now, and mark it - # as ignored for the VCS. - if test ! -d "$build_aux"; then - func_show_eval "mkdir '$build_aux'" - - test -n "$vc_ignore_files" \ - || func_insert_if_absent "$build_aux" $vc_ignore_files - fi - - require_build_aux=: -} - - -# require_buildreq_autobuild -# -------------------------- -# Try to find whether the bootstrap requires autobuild. -require_buildreq_autobuild=func_require_buildreq_autobuild -func_require_buildreq_autobuild () -{ - $debug_cmd - - $require_macro_dir - - test -f "$macro_dir/autobuild.m4" \ - || printf '%s\n' "$buildreq" |func_grep_q '^[ ]*autobuild' \ - || { - func_extract_trace AB_INIT - test -n "$func_extract_trace_result" && { - func_append buildreq 'autobuild - http://josefsson.org/autobuild/ -' - func_verbose "auto-adding 'autobuild' to build requirements" - } - } - - require_buildreq_autobuild=: -} - - -# require_buildreq_autoconf -# require_buildreq_autopoint -# require_buildreq_libtoolize -# --------------------------- -# Try to find the minimum compatible version of autoconf/libtool -# required to bootstrap successfully, and add it to '$buildreq'. -for tool in autoconf libtoolize autopoint; do - b=$tool - v=require_buildreq_${tool} - f=func_$v - case $tool in - autoconf) m=AC_PREREQ ;; - libtoolize) m=LT_PREREQ; b=libtool ;; - autopoint) m=AM_GNU_GETTEXT_VERSION b=gettext ;; - esac - - eval $v'='$f' - '$f' () - { - $debug_cmd - - # The following is ignored if undefined, but might be necessary - # in order for `func_find_tool` to run. - ${require_'$tool'-:} - - printf '\''%s\n'\'' "$buildreq" |func_grep_q '\''^[ ]*'$tool\'' || { - func_extract_trace '$m' - _G_version=$func_extract_trace_result - test -n "$_G_version" && { - func_append buildreq "\ - '$tool' $_G_version http://www.gnu.org/s/'$b' -" - func_verbose \ - "auto-adding '\'$tool'-$_G_version'\'' to build requirements" - } - } - - '$v'=: - } -' -done - - -# require_buildreq_automake -# ------------------------- -# Try to find the minimum compatible version of automake required to -# bootstrap successfully, and add it to '$buildreq'. -require_buildreq_automake=func_require_buildreq_automake -func_require_buildreq_automake () -{ - $debug_cmd - - # if automake is not already listed in $buildreq... - printf '%s\n' "$buildreq" |func_grep_q automake || { - func_extract_trace AM_INIT_AUTOMAKE - - # ...and AM_INIT_AUTOMAKE is declared... - test -n "$func_extract_trace_result" && { - automake_version=`$ECHO "$func_extract_trace_result" \ - |$SED -e 's|[^0-9]*||' -e 's| .*$||'` - test -n "$automake_version" || automake_version=- - - func_append buildreq "\ - automake $automake_version http://www.gnu.org/s/automake -" - func_verbose \ - "auto-adding 'automake-$automake_version' to build requirements" - } - } - - require_buildreq_automake=: -} - - -# require_buildreq_patch -# ---------------------- -# Automatically add a patch build-requirement if there are diff files -# in $local_gl_dir. -require_buildreq_patch=func_require_buildreq_patch -func_require_buildreq_patch () -{ - $debug_cmd - - $require_local_gl_dir - - # This ensures PATCH is set appropriately by the time - # func_check_versions enforces $buildreq. - $require_patch - - # If patch is not already listed in $buildreq... - printf '%s\n' "$buildreq" |func_grep_q '^[ ]*patch' || { - # The ugly find invocation is necessary to exit with non-zero - # status for old find binaries that don't support -exec fully. - if test ! -d "$local_gl_dir" \ - || find "$local_gl_dir" -name "*.diff" -exec false {} \; ; then : - else - func_append buildreq 'patch - http://www.gnu.org/s/patch -' - fi - } - - require_buildreq_patch=: -} - - -# require_buildtools_uptodate -# --------------------------- -# Ensure all the packages listed in BUILDREQS are available on the build -# machine at the minimum versions or better. -require_buildtools_uptodate=func_require_buildtools_uptodate -func_require_buildtools_uptodate () -{ - $debug_cmd - - $require_buildreq_autobuild - $require_buildreq_autoconf - $require_buildreq_automake - $require_buildreq_libtoolize - $require_buildreq_autopoint - $require_buildreq_patch - - test -n "$buildreq" && { - _G_error_hdr= - - func_check_versions $buildreq - $func_check_versions_result || { - test -n "$buildreq_readme" \ - && test -f "$buildreq_readme" \ - && _G_error_hdr="\ -$buildreq_readme explains how to obtain these prerequisite programs: -" - func_strtable 0 11 12 36 \ - "Program" "Min_version" "Homepage" $buildreq - func_fatal_error "$_G_error_hdr$func_strtable_result" - } - } - - require_buildtools_uptodate=: -} - - -# require_copyright_holder -# ------------------------ -# Ensure there is a sensible non-empty default value in '$copyright_holder'. -require_copyright_holder=func_require_copyright_holder -func_require_copyright_holder () -{ - $debug_cmd - - test -n "$copyright_holder" || { - copyright_holder='Free Software Foundation, Inc.' - func_warning settings "\ -Please set copyright_holder explicitly in 'bootstrap.conf'; -defaulting to '$copyright_holder'." - } - - require_copyright_holder=: -} - - -# require_doc_base -# ---------------- -# Ensure doc_base has a sensible value, extracted from 'gnulib-cache.m4' -# if possible, otherwise letting 'gnulib-tool' pick a default. -require_doc_base=func_require_doc_base -func_require_doc_base () -{ - $debug_cmd - - $require_gnulib_cache - - test -f "$gnulib_cache" && test -z "$doc_base" && { - func_extract_trace_first "gl_DOC_BASE" "$gnulib_cache" - doc_base=$func_extract_trace_first_result - - test -n "$doc_base" && func_verbose "doc_base='$doc_base'" - } - - require_doc_base=: -} - - -# require_dotgitmodules -# --------------------- -# Ensure we have a '.gitmodules' file, with appropriate 'gnulib' settings. -require_dotgitmodules=func_require_dotgitmodules -func_require_dotgitmodules () -{ - $debug_cmd - - $require_git - - test true = "$GIT" || { - # A gnulib entry in .gitmodules always takes precedence. - _G_path=`$GIT config --file .gitmodules submodule.gnulib.path 2>/dev/null` - - test -n "$_G_path" || { - $require_vc_ignore_files - - func_verbose "creating '.gitmodules'" - - # If the .gitmodules file doesn't exist, create it now, and mark - # it as ignored for the VCS. - test -n "$gnulib_path" || gnulib_path=gnulib - test -n "$gnulib_url" || gnulib_url=git://git.sv.gnu.org/gnulib - - { - echo '[submodule "gnulib"]' - echo " path = $gnulib_path" - echo " url = $gnulib_url" - } >> .gitmodules - - test -n "$vc_ignore_files" \ - || func_insert_if_absent ".gitmodules" $vc_ignore_files - } - } - - require_dotgitmodules=: -} - - -# require_extra_locale_categories -# ------------------------------- -# Ensure there is a default value in '$extra_locale_categories' -require_extra_locale_categories=func_require_extra_locale_categories -func_require_extra_locale_categories () -{ - $debug_cmd - - # Defaults to empty, so run with whatever value may have been set in - # 'bootstrap.conf'. - require_extra_locale_categories=: -} - - -# require_git -# ----------- -# Ignore git if it's not available, or we're not in a git checkout tree. -require_git=func_require_git -func_require_git () -{ - $debug_cmd - - $opt_skip_git && GIT=true - - test true = "$GIT" || { - if test -d .git/.; then - ($GIT --version) >/dev/null 2>&1 || GIT=true - fi - } - - func_verbose "GIT='$GIT'" - - require_git=: -} - - -# require_gnulib_cache -# -------------------- -# Ensure there is a non-empty default for '$gnulib_cache', and that it -# names an existing file. -require_gnulib_cache=func_require_gnulib_cache -func_require_gnulib_cache () -{ - $debug_cmd - - $require_macro_dir - - test -n "$gnulib_cache" \ - || gnulib_cache=$macro_dir/gnulib-cache.m4 - - func_verbose "found '$gnulib_cache'" - - require_gnulib_cache=: -} - - -# require_gnulib_copy_cmd -# ----------------------- -# Only calculate the options for copying files with gnulib once. -require_gnulib_copy_cmd=func_require_gnulib_copy_cmd -func_require_gnulib_copy_cmd () -{ - $debug_cmd - - $require_gnulib_tool - $require_gnulib_tool_base_options - - gnulib_copy_cmd="$gnulib_tool $gnulib_tool_base_options --copy-file" - $opt_copy || func_append gnulib_copy_cmd " --symlink" - $opt_quiet || func_append gnulib_copy_cmd " --verbose" - - require_gnulib_copy_cmd=: -} - - -# require_gnulib_merge_changelog -# ------------------------------ -# See if we can use gnulib's git-merge-changelog merge driver. -require_gnulib_merge_changelog=func_require_gnulib_merge_changelog -func_require_gnulib_merge_changelog () -{ - $debug_cmd - - test -f ChangeLog && { - $require_git - - func_grep_q '^\(/\|\)ChangeLog$' .gitignore || test true = "$GIT" || { - if $GIT config merge.merge-changelog.driver >/dev/null; then - : - elif (git-merge-changelog --version) >/dev/null 2>&1; then - func_echo "initializing git-merge-changelog driver" - $GIT config merge.merge-changelog.name 'GNU-style ChangeLog merge driver' - $GIT config merge.merge-changelog.driver 'git-merge-changelog %O %A %B' - else - func_warning recommend \ - "Consider installing git-merge-changelog from gnulib." - fi - } - } - - require_gnulib_merge_changelog=: -} - - -# require_gnulib_mk -# ----------------- -# Ensure gnulib_mk has a sensible value, extracted from 'gnulib-cache.m4' -# if possible, otherwise letting 'gnulib-tool' pick a default. -require_gnulib_mk=func_require_gnulib_mk -func_require_gnulib_mk () -{ - $debug_cmd - - $require_gnulib_cache - - test -f "$gnulib_cache" && test -z "$gnulib_mk" && { - func_extract_trace_first "gl_MAKEFILE_NAME" "$gnulib_cache" - gnulib_mk=$func_extract_trace_first_result - - test -n "$gnulib_mk" && func_verbose "gnulib_mk='$gnulib_mk'" - } - - require_gnulib_mk=: -} - - -# require_gnulib_name -# ------------------- -# Ensure gnulib_name has a sensible value, extracted from 'gnulib-cache.m4' -# if possible, otherwise letting 'gnulib-tool' pick a default. -require_gnulib_name=func_require_gnulib_name -func_require_gnulib_name () -{ - $debug_cmd - - $require_gnulib_cache - - test -f "$gnulib_cache" && test -z "$gnulib_name" && { - func_extract_trace_first "gl_LIB" "$gnulib_cache" - gnulib_name=$func_extract_trace_first_result - - test -n "$gnulib_name" && func_verbose "gnulib_name='$gnulib_name'" - } - - require_gnulib_name=: -} - - -# require_gnulib_path -# require_gnulib_url -# ------------------- -# Ensure 'gnulib_path' and 'gnulib_url' are set. -require_gnulib_path=func_require_dotgitmodules_parameters -require_gnulib_url=func_require_dotgitmodules_parameters -func_require_dotgitmodules_parameters () -{ - $debug_cmd - - $require_git - - test true = "$GIT" && { - # If we can't find git (or if the user specified '--skip-git'), - # then use an existing gnulib directory specified with - # '--gnulib-srcdir' if possible. - test -n "$gnulib_path" \ - || test ! -x "$opt_gnulib_srcdir/gnulib-tool" \ - || gnulib_path=$opt_gnulib_srcdir - } - - - $require_dotgitmodules - - test -f .gitmodules && { - # Extract the parameters with sed, since git may be missing - test -n "$gnulib_path" \ - || gnulib_path=`$SED -e '/^.submodule "gnulib".$/,${ - /[ ]*path *= */{ - s|[ ]*||g;s|^[^=]*=||;p - } - } - d' .gitmodules |$SED 1q` - test -n "$gnulib_url" \ - || gnulib_url=`$SED -e '/^.submodule "gnulib".$/,${ - /[ ]*url *= */{ - s|[ ]*||g;s|^[^=]*=||;p - } - } - d' .gitmodules |$SED 1q` - - func_verbose "gnulib_path='$gnulib_path'" - func_verbose "gnulib_url='$gnulib_url'" - } - - require_gnulib_path=: - require_gnulib_url=: -} - - -# require_gnulib_submodule -# ------------------------ -# Ensure that there is a current gnulib submodule at '$gnulib_path'. -require_gnulib_submodule=func_require_gnulib_submodule -func_require_gnulib_submodule () -{ - $debug_cmd - - $require_git - - if test true = "$GIT"; then - func_warning recommend \ - "No 'git' found; imported gnulib modules may be outdated." - else - $require_gnulib_path - $require_gnulib_url - - if test -f .gitmodules && test -f "$gnulib_path/gnulib-tool"; then - : All present and correct. - - elif test -n "$opt_gnulib_srcdir"; then - # Older git can't clone into an empty directory. - rmdir "$gnulib_path" 2>/dev/null - func_show_eval "$GIT clone --reference '$opt_gnulib_srcdir' \ - '$gnulib_url' '$gnulib_path'" \ - || func_fatal_error "Unable to fetch gnulib submodule." - - # Without --gnulib-srcdir, and no existing checked out submodule, we - # create a new shallow clone of the remote gnulib repository. - else - trap func_cleanup_gnulib 1 2 13 15 - - shallow= - $GIT clone -h 2>&1 |func_grep_q -- --depth \ - && shallow='--depth 365' - - func_show_eval "$GIT clone $shallow '$gnulib_url' '$gnulib_path'" \ - func_cleanup_gnulib - - # FIXME: Solaris /bin/sh will try to execute '-' if any of - # these signals are caught after this. - trap - 1 2 13 15 - fi - - # Make sure we've checked out the correct revision of gnulib. - func_show_eval "$GIT submodule init -- $gnulib_path" \ - && func_show_eval "$GIT submodule update -- $gnulib_path" \ - || func_fatal_error "Unable to update gnulib submodule." - fi - - require_gnulib_submodule=: -} - - -# require_gnulib_tool -# ------------------- -# Ensure that '$gnulib_tool' is set, and points to an executable file, -# or else fall back to using the binary 'true' if the main gnulib -# files appear to have been imported already. -require_gnulib_tool=func_require_gnulib_tool -func_require_gnulib_tool () -{ - $debug_cmd - - test true = "$gnulib_tool" || { - $require_gnulib_submodule - $require_gnulib_path - - test -n "$gnulib_tool" \ - || gnulib_tool=$gnulib_path/gnulib-tool - - test -x "$gnulib_tool" || { - gnulib_tool=true - func_warning recommend \ - "No 'gnulib-tool' found; gnulib modules may be missing." - } - - test true = "$gnulib_tool" \ - || func_verbose "found '$gnulib_tool'" - } - - require_gnulib_tool=: -} - - -# require_gnulib_tool_base_options -# -------------------------------- -# Ensure that '$gnulib_tool_base_options' contains all the base options -# required according to user configuration from bootstrap.conf. -require_gnulib_tool_base_options=func_require_gnulib_tool_base_options -func_require_gnulib_tool_base_options () -{ - $debug_cmd - - $require_gnulib_tool - - gnulib_tool_base_options= - - test true = "$gnulib_tool" || { - # 'gnulib_modules' and others are maintained in 'bootstrap.conf': - # Use 'gnulib --import' to fetch gnulib modules. - $require_build_aux - test -n "$build_aux" \ - && func_append_uniq gnulib_tool_base_options " --aux-dir=$build_aux" - $require_macro_dir - test -n "$macro_dir" \ - && func_append_uniq gnulib_tool_base_options " --m4-base=$macro_dir" - $require_doc_base - test -n "$doc_base" \ - && func_append_uniq gnulib_tool_base_options " --doc-base=$doc_base" - $require_gnulib_name - test -n "$gnulib_name" \ - && func_append_uniq gnulib_tool_base_options " --lib=$gnulib_name" - $require_local_gl_dir - test -n "$local_gl_dir" \ - && func_append_uniq gnulib_tool_base_options " --local-dir=$local_gl_dir" - $require_source_base - test -n "$source_base" \ - && func_append_uniq gnulib_tool_base_options " --source-base=$source_base" - } - - require_gnulib_tool_base_options=: -} - - -# require_libtoolize -# ------------------ -# Skip libtoolize if it's not needed. -require_libtoolize=func_require_libtoolize -func_require_libtoolize () -{ - $debug_cmd - - # Unless we're not searching for libtool use by this package, set - # LIBTOOLIZE to true if none of 'LT_INIT', 'AC_PROG_LIBTOOL' and - # 'AM_PROG_LIBTOOL' are used in configure. - test true = "$LIBTOOLIZE" || { - func_extract_trace LT_INIT - test -n "$func_extract_trace_result" || func_extract_trace AC_PROG_LIBTOOL - test -n "$func_extract_trace_result" || func_extract_trace AM_PROG_LIBTOOL - test -n "$func_extract_trace_result" || LIBTOOLIZE=true - } - - test -n "$LIBTOOLIZE" || { - # Find libtoolize, named glibtoolize in Mac Ports, but prefer - # user-installed libtoolize to ancient glibtoolize shipped by - # Apple with Mac OS X when Mac Ports is not installed. - func_find_tool LIBTOOLIZE libtoolize glibtoolize - } - - test -n "$LIBTOOLIZE" || func_fatal_error "\ -Please install GNU Libtool, or 'export LIBTOOLIZE=/path/to/libtoolize'." - - func_verbose "export LIBTOOLIZE='$LIBTOOLIZE'" - - # Make sure the search result is visible to subshells - export LIBTOOLIZE - - require_libtoolize=: -} - - -# require_local_gl_dir -# -------------------- -# Ensure local_gl_dir has a sensible value, extracted from 'gnulib-cache.m4' -# if possible, otherwise letting 'gnulib-tool' pick a default. -require_local_gl_dir=func_require_local_gl_dir -func_require_local_gl_dir () -{ - $debug_cmd - - $require_gnulib_cache - - test -f "$gnulib_cache" && test -z "$local_gl_dir" && { - func_extract_trace_first "gl_LOCAL_DIR" "$gnulib_cache" - local_gl_dir=$func_extract_trace_first_result - - test -n "$local_gl_dir" && func_verbose "local_gl_dir='$local_gl_dir'" - } - - require_local_gl_dir=: -} - - -# require_macro_dir -# ----------------- -# Ensure that '$macro_dir' is set, and if it doesn't already point to an -# existing directory, create one. -require_macro_dir=func_require_macro_dir -func_require_macro_dir () -{ - $debug_cmd - - # Sometimes this is stored in 'configure.ac'. - test -n "$macro_dir" || { - # AC_CONFIG_MACRO_DIRS takes a space delimited list of directories, - # but we only care about the first one in bootstrap. - func_extract_trace_first AC_CONFIG_MACRO_DIRS - macro_dir=`expr "x$func_extract_trace_first_result" : 'x\([^ ]*\)'` - } - test -n "$macro_dir" || { - func_extract_trace_first AC_CONFIG_MACRO_DIR - macro_dir=$func_extract_trace_first_result - } - - # Otherwise we might find it in 'Makefile.am'. - test -n "$macro_dir" || { - $require_aclocal_amflags - - # Take the argument following the first '-I', if any. - _G_minus_I_seen=false - for _G_arg in $aclocal_amflags; do - case $_G_minus_I_seen,$_G_arg in - :,*) macro_dir=$_G_arg; break ;; - *,-I) _G_minus_I_seen=: ;; - *,-I*) macro_dir=`expr x$_G_arg : 'x-I\(.*\)$'`; break ;; - esac - done - } - - func_verbose "macro_dir='$macro_dir'" - - func_check_configuration macro_dir \ - "AC_CONFIG_MACRO_DIRS([name of a directory for configure m4 files])" - - $require_vc_ignore_files - - # If the macro_dir directory doesn't exist, create it now, and mark it - # as ignored for the VCS. - if test ! -d "$macro_dir"; then - mkdir "$macro_dir" || func_permissions_error "$macro_dir" - - test -n "$vc_ignore_files" \ - || func_insert_if_absent "$macro_dir" $vc_ignore_files - fi - - require_macro_dir=: -} - - -# require_makefile_am -# ------------------- -# Ensure there is a 'Makefile.am' in the current directory. -require_makefile_am=func_require_makefile_am -func_require_makefile_am () -{ - $debug_cmd - - test -n "$makefile_am" \ - || makefile_am=Makefile.am - - <"$makefile_am" - - func_verbose "found '$makefile_am'" - - require_makefile_am=: -} - - -# require_package -# --------------- -# Ensure that '$package' contains a sensible default value. -require_package=func_require_package -func_require_package () -{ - $debug_cmd - - test -n "$package" || { - $require_package_name - - package=`echo "$package_name" \ - |$SED -e 's/GNU //' \ - -e 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/'` - } - - func_verbose "package='$package'" - - require_package=: -} - - -# require_package_bugreport -# ------------------------- -# Ensure that this has a sensible value, extracted from 'configure.ac' -# if appropriate (and possible!). -require_package_bugreport=func_require_package_bugreport -func_require_package_bugreport () -{ - $debug_cmd - - func_extract_trace AC_INIT - - save_ifs=$IFS - IFS=: - set dummy $func_extract_trace_result - IFS=$save_ifs - shift - - test -n "$package_bugreport" || package_bugreport=$3 - func_check_configuration package_bugreport \ - "AC_INIT([$package_name], [$package_version], [bug-$package@gnu.org])" - func_verbose "package_bugreport='$package_bugreport'" - - require_package_bugreport=: -} - - -# require_package_name -# -------------------- -# Ensure that this has a sensible value, extracted from 'configure.ac' -# if appropriate (and possible!). -require_package_name=func_require_package_name -func_require_package_name () -{ - $debug_cmd - - func_extract_trace AC_INIT - - save_ifs=$IFS - IFS=: - set dummy $func_extract_trace_result - IFS=$save_ifs - shift - - test -n "$package_name" || package_name=$1 - func_check_configuration package_name \ - "AC_INIT([name of your package], [package version number])" - func_verbose "package_name='$package_name'" - - require_package_name=: -} - - -# require_package_version -# ----------------------- -# Ensure that this has a sensible value, extracted from 'configure.ac' -# if appropriate (and possible!). While we might have set all the -# parameters extracted from AC_INIT at once, 'package_version' in -# particular is not necessarily available as early as the others, since -# 'git-version-gen' is often involved, and until then we can't rely on -# getting a correct version number from an AC_INIT extraction. -require_package_version=func_require_package_version -func_require_package_version () -{ - $debug_cmd - - func_extract_trace AC_INIT - - save_ifs=$IFS - IFS=: - set dummy $func_extract_trace_result - IFS=$save_ifs - shift - - test -n "$package_version" || package_version=$2 - test -n "$package_version" || { - # The embedded echo is to squash whitespace before globbing. - case " "`echo $gnulib_modules`" " in - *" git-version-gen "*) - func_fatal_error "\ -cannot \$require_package_version in bootstrap.conf before -func_gnulib_tool has installed the 'git-version-gen' script." - ;; - *) - func_check_configuration package_version \ - "AC_INIT([name of your package], [package version number])" - ;; - esac - } - func_verbose "package_version='$package_version'" - - require_package_version=: -} - - -# require_patch -# ------------- -# Find patch, according to the PATCH environment variable, or else -# searching the user's PATH. -require_patch=func_require_patch -func_require_patch () -{ - $debug_cmd - - test -n "$PATCH" || { - # Find a patch program, preferring gpatch, which is usually better - # than the vendor patch. - func_find_tool PATCH gpatch patch - } - - test -n "$PATCH" || func_fatal_error "\ -Please install GNU Patch, or 'export PATCH=/path/to/gnu/patch'." - - func_verbose "export PATCH='$PATCH'" - - # Make sure the search result is visible to subshells - export PATCH - - require_patch=: -} - - -# require_source_base -# ------------------- -# Ensure that source_base has a sensible value, extracted from -# 'gnulib-cache.m4' if possible. -require_source_base=func_require_source_base -func_require_source_base () -{ - $debug_cmd - - $require_gnulib_cache - - test -f "$gnulib_cache" && test -z "$source_base" && { - func_extract_trace_first "gl_SOURCE_BASE" "$gnulib_cache" - - source_base=$func_extract_trace_first_result - - func_verbose "source_base='$source_base'" - } - - require_source_base=: -} - - -# require_vc_ignore_files -# ----------------------- -# Ensure that '$vc_ignore' has been processed to list VCS ignore files -# in '$vc_ignore_files' -require_vc_ignore_files=func_require_vc_ignore_files -func_require_vc_ignore_files () -{ - $debug_cmd - - test -n "$vc_ignore" || vc_ignore=auto - - if test auto = "$vc_ignore" && test -z "$vc_ignore_files"; then - vc_ignore_files= - test -d .git && vc_ignore_files=.gitignore - test -d CVS && vc_ignore_files="$vc_ignore_files .cvsignore" - else - vc_ignore_files=$vc_ignore - fi - - func_verbose "vc_ignore_files='$vc_ignore_files'" - - require_vc_ignore_files=: -} - - -## ----------------- ## -## Helper functions. ## -## ----------------- ## - -# This section contains the helper functions used by the rest of 'bootstrap'. - -# func_len STRING -# --------------- -# STRING may not start with a hyphen. -if (eval 'x=123; test x${#x} = "x3"') 2>/dev/null -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_len () - { - $debug_cmd - - func_len_result=${#1} - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_len () - { - $debug_cmd - - func_len_result=`expr "$1" : ".*" 2>/dev/null || echo 0` - } -fi - - -# func_unset VAR -# -------------- -# Portably unset VAR. -# In some shells, an 'unset VAR' statement leaves a non-zero return -# status if VAR is already unset, which might be problematic if the -# statement is used at the end of a function (thus poisoning its return -# value) or when 'set -e' is active (causing even a spurious abort of -# the script in this case). -func_unset () -{ - { eval $1=; unset $1; } -} -unset=func_unset - - -# func_cmp_s FILE1 FILE2 -# ---------------------- -# Return non-zero exit status unless FILE1 and FILE2 are identical, without -# any output at all, even error messages. -func_cmp_s () -{ - $debug_cmd - - # This function relies on non-zero exit status, which will cause the - # program to exit when running in 'set -e' mode. - $CMP "$@" >/dev/null 2>&1 -} - - -# func_grep_q EXPRESSION [FILENAME..] -# ----------------------------------- -# Check whether EXPRESSION matches any line of any listed FILENAME, -# without any output at all, even error messages. -func_grep_q () -{ - $debug_cmd - - # This function relies on non-zero exit status, which will cause the - # program to exit when running in 'set -e' mode. - $GREP "$@" >/dev/null 2>&1 -} - - -# func_ifcontains LIST MEMBER YES-CMD [NO-CMD] -# -------------------------------------------- -# If whitespace-separated LIST contains MEMBER then execute YES-CMD, -# otherwise if NO-CMD was given, execute that. -func_ifcontains () -{ - $debug_cmd - - _G_wslist=$1 - _G_member=$2 - _G_yes_cmd=$3 - _G_no_cmd=${4-":"} - - _G_found=false - for _G_item in $_G_wslist; do - test "x$_G_item" = "x$_G_member" && { - _G_found=: - break - } - done - if $_G_found; then - eval "$_G_yes_cmd" - _G_status=$? - else - eval "$_G_no_cmd" - _G_status=$? - fi - - test 0 -eq "$_G_status" || exit $_G_status -} - - -# func_strpad STR WIDTH CHAR -# -------------------------- -# Trim STR, or pad with CHAR to force a total length of WIDTH. -func_strpad () -{ - $debug_cmd - - _G_width=`expr "$2" - 1` - func_strpad_result=`$ECHO "$1" |$SED ' - :a - s|^.\{0,'"$_G_width"'\}$|&'"$3"'| - ta - '` -} - - -# func_strrpad STR WIDTH CHAR -# --------------------------- -# Trim STR, or right-justify-pad with CHAR to force a total length of -# WIDTH. -func_strrpad () -{ - $debug_cmd - - _G_width=`expr "$2" - 1` - func_strrpad_result=`$ECHO "$1" |$SED ' - :a - s|^.\{0,'"$_G_width"'\}$|'"$3"'&| - ta - '` -} - - -# func_strrow INDENT FIELD WIDTH [FIELDn WIDTHn]... -# ------------------------------------------------- -# Return a string containing each FIELD left justified to WIDTH, with -# the whole thing indented by INDENT spaces. This function is used to -# render one row of aligned columns for a table by func_strtable(). -func_strrow () -{ - $debug_cmd - - func_strrow_linelen=$1; shift - - _G_row= - while test $# -gt 0; do - func_strrow_linelen=`expr $func_strrow_linelen + $2` - func_strpad "$1" $2 " " - func_append _G_row "$func_strpad_result" - shift; shift - done - - func_strrpad "$_G_row" $func_strrow_linelen " " - func_strrow_result=$func_strrpad_result -} - - -# func_strtable INDENT WIDTH1...WIDTHn HEADER1...HEADERn FIELD1...FIELDn -# ---------------------------------------------------------------------- -# Generate a string of newline-separated rows arranged in lined-up -# columns of the given WIDTHs, with the entire table indented by INDENT -# spaces. The number of columns is determined by the number of integer -# valued WIDTH arguments following INDENT. The next set (i.e. a number -# of arguments equal to the number of WIDTH arguments) of fields are -# treated as the table's column HEADERs, and are separated from the -# remainder of the table by an indented row of '-' characters. Remaining -# arguments are each aligned below the next available header, wrapping -# to a new row as necessary. Finally another row of '-' characters is -# added to mark the end of the table. -# -# For example an unindented 3 column table with 2 rows of data would be -# generated by this call: -# -# func_strtable 3 20 10 25 \ -# Header1 Header2 Header3 \ -# Row1Col1 Row1Col2 Row1Col3 \ -# Row2Col1 Row2Col2 Row2Col3 -# -# returning the following string: -# -# " Header1 Header2 Header3 -# ------------------------------------------------------- -# Row1Col1 Row1Col2 Row1Col3 -# Row2Col1 Row2Col2 Row2Col3 -# -------------------------------------------------------" -func_strtable () -{ - $debug_cmd - - # Save the indent value, we'll need it for each row we render. - _G_indent=$1; shift - - # Collect remaining numeric args into a list for reuse between - # members of each row when we call func_strrow later. - _G_widths=$1; shift - while test 0 -lt `expr "$1" : '[1-9][0-9]*$'`; do - func_append _G_widths " $1"; shift - done - - # Extract the same number of positional parameters as there are - # width elements - we'll do the header rows separately so that - # we can insert a divider line. - _G_header=$_G_indent - for _G_width in $_G_widths; do - func_append _G_header " $1 $_G_width"; shift - done - func_strrow $_G_header - - # Strip off the indent, and make a divider with '-' chars, then - # reindent. - _G_divider=`$ECHO "$func_strrow_result" \ - |$SED 's|[^ ]|-|g - :a - s|- |--|g - ta - '` - - # Append the header and divider to the running result. - func_append func_strtable_result "\ -$func_strrow_result -$_G_divider -" - - # The remaining rows are zipped between the width values we - # unwound earlier just like the header row above. - while test $# -gt 0; do - _G_row=$_G_indent - for _G_width in $_G_widths; do - func_append _G_row " $1 $_G_width"; shift - done - func_strrow $_G_row - func_append func_strtable_result "\ -$func_strrow_result -" - done - - # Mark the end of the table with a final divider line. - func_append func_strtable_result "$_G_divider" -} - - -# func_internal_error ARG... -# -------------------------- -# Echo program name prefixed message to standard error, and exit. -func_internal_error () -{ - func_fatal_error "\ -INTERNAL: " ${1+"$@"} " - Please report this bug to 'bug-gnulib@gnu.org' - in as much detail as possible." -} - - -# func_permissions_error FILE-OR-DIRECTORY -# ---------------------------------------- -# Echo program name prefixed permissions error message to standard -# error, and exit. -func_permissions_error () -{ - $debug_cmd - - func_fatal_error "Failed to create '$1', check permissions." -} - - -# func_show_eval CMD [FAIL_EXP] -# ----------------------------- -# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () -{ - $debug_cmd - - $require_term_colors - - _G_cmd=$1 - _G_fail_exp=${2-':'} - - ${opt_silent-'false'} || { - func_quote_for_eval $_G_cmd - eval func_truncate_cmd $func_quote_for_eval_result - func_echo "running: $tc_bold$func_truncate_cmd_result$tc_reset" - } - - ${opt_dry_run-'false'} || { - eval "$_G_cmd" - _G_status=$? - test 0 -eq "$_G_status" || eval "(exit $_G_status); $_G_fail_exp" - } -} - - -# func_truncate_cmd CMD [ARG]... -# ------------------------------ -# For unreasonably long commands (such as a gnulib-tool invocation with -# the full module list for import), truncate CMD after the second non- -# option ARG. -func_truncate_cmd () -{ - $debug_cmd - - _G_last_arg_opt_p=false - func_truncate_cmd_result= - - set dummy "$@"; shift - - while test $# -gt 0; do - _G_opt=$1; shift - - test -n "$func_truncate_cmd_result" \ - && func_append func_truncate_cmd_result ' ' - func_append func_truncate_cmd_result "$_G_opt" - - func_len "x$func_truncate_cmd_result" - - case $_G_opt in - -*) _G_last_arg_opt_p=: ;; - *) $_G_last_arg_opt_p \ - || test "$min_cmd_len" -gt "$func_len_result" \ - || break - _G_last_arg_opt_p=false - ;; - esac - done - - test $# -gt 0 && func_append func_truncate_cmd_result "..." -} - - -# func_gitignore_entries FILE... -# ------------------------------ -# Strip blank and comment lines to leave significant entries. -func_gitignore_entries () -{ - $debug_cmd - - $SED -e '/^#/d' -e '/^$/d' "$@" -} - - -# func_insert_if_absent STR FILE... -# --------------------------------- -# If $STR is not already on a line by itself in $FILE, insert it, at the -# start. Entries are inserted at the start of the ignore list to ensure -# existing entries starting with ! are not overridden. Such entries -# support whilelisting exceptions after a more generic blacklist pattern. -# sorting the new contents of the file and replacing $FILE with the result. -func_insert_if_absent () -{ - $debug_cmd - - str=$1 - shift - - for file - do - test -f "$file" || touch "$file" - - duplicate_entries=`func_gitignore_entries "$file" |sort |uniq -d` - test -n "$duplicate_entries" \ - && func_error "duplicate entries in $file: " $duplicate_entries - - func_grep_q "^$str\$" "$file" \ - || func_verbose "inserting '$str' into '$file'" - - linesold=`func_gitignore_entries "$file" |wc -l` - linesnew=`{ $ECHO "$str"; cat "$file"; } \ - |func_gitignore_entries |sort -u |wc -l` - test "$linesold" -eq "$linesnew" \ - || { $SED "1i\\$nl$str$nl" "$file" >"$file"T && mv "$file"T "$file"; } \ - || func_permissions_error "$file" - done -} - - -# func_get_version APP -# -------------------- -# echo the version number (if any) of APP, which is looked up along your -# PATH. -func_get_version () -{ - $debug_cmd - - _G_app=$1 - - # Rather than uncomment the sed script in-situ, strip the comments - # programatically before passing the result to $SED for evaluation. - sed_get_version=`$ECHO '# extract version within line - s|.*[v ]\{1,\}\([0-9]\{1,\}\.[.a-z0-9-]*\).*|\1| - t done - - # extract version at start of line - s|^\([0-9]\{1,\}\.[.a-z0-9-]*\).*|\1| - t done - - d - - :done - # the following essentially does s|5.005|5.5| - s|\.0*\([1-9]\)|.\1|g - p - q' \ - |$SED '/^[ ]*#.*$/d'` - - func_tool_version_output $_G_app >/dev/null - _G_status=$? - - test 0 -ne "$_G_status" \ - || $_G_app --version 2>&1 |$SED -n "$sed_get_version" - - (exit $_G_status) -} - - -# func_check_tool APP -# ------------------- -# Search PATH for an executable at APP. -func_check_tool () -{ - $debug_cmd - - func_check_tool_result= - - case $1 in - *[\\/]*) - test -x "$1" && func_check_tool_result=$1 - ;; - *) - save_IFS=$IFS - IFS=${PATH_SEPARATOR-:} - for _G_check_tool_path in $PATH; do - IFS=$save_IFS - if test -x "$_G_check_tool_path/$1"; then - func_check_tool_result=$_G_check_tool_path/$1 - break - fi - done - IFS=$save_IFS - ;; - esac -} - - -# func_check_versions APP1 VER1 URL1 ...[APPN VERN URLN] -# ------------------------------------------------------ -func_check_versions () -{ - $debug_cmd - - func_check_versions_result=: - - while test $# -gt 0; do - _G_app=$1; shift - _G_reqver=$1; shift - _G_url=$1; shift - - # Diagnose bad buildreq formatting. - case $_G_url in - [a-z]*://*) ;; # looks like a url - *) func_fatal_error "\ -'$_G_url' from the buildreq table in -'bootstrap.conf' does not look like the URL for downloading -$_G_app. Please ensure that buildreq is a strict newline -delimited list of triples; 'program min-version url'." - ;; - esac - - # Honor $APP variables ($TAR, $AUTOCONF, etc.) - _G_appvar=`echo $_G_app |tr '[a-z]' '[A-Z]'` - test TAR = "$_G_appvar" && _G_appvar=AMTAR - eval "_G_app=\${$_G_appvar-$_G_app}" - - # Fail if no version specified, but the program can't be found. - if test x- = "x$_G_reqver"; then - func_check_tool $_G_app - if test -z "$func_check_tool_result"; then - func_error "Prerequisite '$_G_app' not not found. Please install it, or -'export $_G_appvar=/path/to/$_G_app'." - func_check_versions_result=false - else - func_verbose "found '$func_check_tool_result' for $_G_appvar." - fi - else - _G_instver=`func_get_version $_G_app` - - # Fail if --version didn't work. - if test -z "$_G_instver"; then - func_error "Prerequisite '$_G_app' not found. Please install it, or -'export $_G_appvar=/path/to/$_G_app'." - func_check_versions_result=false - - # Fail if a newer version than what we have is required. - else - func_verbose "found '$_G_app' version $_G_instver." - - case $_G_reqver in - =*) - # If $buildreq version starts with '=', version must - # match the installed program exactly. - test "x$_G_reqver" = "x=$_G_instver" || { - func_error "\ - '$_G_app' version == $_G_instver is too old - 'exactly $_G_app-$_G_reqver is required" - func_check_versions_result=false - } - ;; - *) - # Otherwise, anything that is not older is a match. - func_lt_ver "$_G_reqver" "$_G_instver" || { - func_error "\ - '$_G_app' version == $_G_instver is too old - '$_G_app' version >= $_G_reqver is required" - func_check_versions_result=false - } - ;; - esac - fi - fi - done -} - - -# func_cleanup_gnulib -# ------------------- -# Recursively delete everything below the path in the global variable -# GNULIB_PATH. -func_cleanup_gnulib () -{ - $debug_cmd - - _G_status=$? - $RM -fr "$gnulib_path" - exit $_G_status -} - - -# func_download_po_files SUBDIR DOMAIN -# ------------------------------------ -func_download_po_files () -{ - $debug_cmd - - func_echo "getting translations into $1 for $2..." - _G_cmd=`printf "$po_download_command_format" "$2" "$1"` - eval "$_G_cmd" -} - - -# func_update_po_files PO_DIR DOMAIN -# ---------------------------------- -# Mirror .po files to $po_dir/.reference and copy only the new -# or modified ones into $po_dir. Also update $po_dir/LINGUAS. -# Note po files that exist locally only are left in $po_dir but will -# not be included in LINGUAS and hence will not be distributed. -func_update_po_files () -{ - $debug_cmd - - # Directory containing primary .po files. - # Overwrite them only when we're sure a .po file is new. - _G_po_dir=$1 - _G_domain=$2 - - # Mirror *.po files into this dir. - # Usually contains *.s1 checksum files. - _G_ref_po_dir=$_G_po_dir/.reference - - test -d "$_G_ref_po_dir" || mkdir $_G_ref_po_dir || return - func_download_po_files $_G_ref_po_dir $_G_domain \ - && ls "$_G_ref_po_dir"/*.po 2>/dev/null \ - |$SED -e 's|.*/||' -e 's|\.po$||' > "$_G_po_dir/LINGUAS" || return - - # Find sha1sum, named gsha1sum on MacPorts, and shasum on MacOS 10.6+. - func_find_tool SHA1SUM sha1sum gsha1sum shasum sha1 - - test -n "$SHA1SUM" || func_fatal_error "\ -Please install GNU Coreutils, or 'export SHA1SUM=/path/to/sha1sum'." - - _G_langs=`cd $_G_ref_po_dir && echo *.po|$SED 's|\.po||g'` - test '*' = "$_G_langs" && _G_langs=x - for _G_po in $_G_langs; do - case $_G_po in x) continue;; esac - _G_new_po=$_G_ref_po_dir/$_G_po.po - _G_cksum_file=$_G_ref_po_dir/$_G_po.s1 - if ! test -f "$_G_cksum_file" || - ! test -f "$_G_po_dir/$_G_po.po" || - ! $SHA1SUM -c "$_G_cksum_file" \ - < "$_G_new_po" > /dev/null; then - echo "updated $_G_po_dir/$_G_po.po..." - cp "$_G_new_po" "$_G_po_dir/$_G_po.po" \ - && $SHA1SUM < "$_G_new_po" > "$_G_cksum_file" || return - fi - done -} - - - -## --------------- ## -## Option parsing. ## -## --------------- ## - -# Hook in the functions to make sure our own options are parsed during -# the option parsing loop. - -usage='$progpath [OPTION]...' - -# Short help message in response to '-h'. Add to this in 'bootstrap.conf' -# if you accept any additional options. -usage_message="Common Bootstrap Options: - -c, --copy copy files instead of creating symbolic links. - --debug enable verbose shell tracing - -n, --dry-run print commands rather than running them - -f, --force attempt to bootstrap even if the sources seem not - to have been checked out. - --gnulib-srcdir=DIRNAME - specify a local directory where gnulib sources - reside. Use this if you already have the gnulib - sources on your machine, and don't want to waste - your bandwidth downloading them again. Defaults to - \$GNULIB_SRCDIR. - --no-warnings equivalent to '-Wnone' - --skip-git do not fetch files from remote repositories - --skip-po do not download po files. - -v, --verbose verbosely report processing - --version print version information and exit - -W, --warnings=CATEGORY - report the warnings falling in CATEGORY [all] - -h, --help print short or long help message and exit -" - -# Additional text appended to 'usage_message' in response to '--help'. -long_help_message=$long_help_message" - 'recommend' show warnings about missing recommended packages - 'settings' show warnings about missing '$progname.conf' settings - 'upgrade' show warnings about out-dated files - -If the file '$progname.conf' exists in the same directory as this -script, its contents are read as shell variables to configure the -bootstrap. - -For build prerequisites, environment variables like \$AUTOCONF and -\$AMTAR are honored. - -Running without arguments will suffice in most cases. -" - -# Warning categories used by 'bootstrap', append others if you use them -# in your 'bootstrap.conf'. -warning_categories='recommend settings upgrade' - - -# bootstrap_options_prep [ARG]... -# ------------------------------- -# Preparation for options parsed by Bootstrap. -bootstrap_options_prep () -{ - $debug_cmd - - # Option defaults: - opt_copy=${copy-'false'} - opt_dry_run=false - opt_force=false - opt_gnulib_srcdir=$GNULIB_SRCDIR - opt_skip_git=false - opt_skip_po=false - - # Pass back the list of options we consumed. - func_quote_for_eval ${1+"$@"} - bootstrap_options_prep_result=$func_quote_for_eval_result -} -func_add_hook func_options_prep bootstrap_options_prep - - -# bootstrap_parse_options [ARG]... -# -------------------------------- -# Provide handling for Bootstrap specific options. -bootstrap_parse_options () -{ - $debug_cmd - - # Perform our own loop to consume as many options as possible in - # each iteration. - while test $# -gt 0; do - _G_opt=$1 - shift - case $_G_opt in - --dry-run|--dryrun|-n) - opt_dry_run=: ;; - --copy|-c) opt_copy=: ;; - --force|-f) opt_force=: ;; - - --gnulib-srcdir) - test $# = 0 && func_missing_arg $_G_opt && break - opt_gnulib_srcdir=$1 - shift - ;; - - --skip-git|--no-git) - opt_skip_git=: - ;; - - --skip-po|--no-po) - opt_skip_po=: - ;; - - # Separate non-argument short options: - -c*|-f*|-n*) - func_split_short_opt "$_G_opt" - set dummy "$func_split_short_opt_name" \ - "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; - esac - done - - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - bootstrap_parse_options_result=$func_quote_for_eval_result -} -func_add_hook func_parse_options bootstrap_parse_options - - -# bootstrap_validate_options [ARG]... -# ----------------------------------- -# Perform any sanity checks on option settings and/or unconsumed -# arguments. -bootstrap_validate_options () -{ - $debug_cmd - - # Validate options. - test $# -gt 0 \ - && func_fatal_help "too many arguments" - - # Pass back the (empty) list of unconsumed options. - func_quote_for_eval ${1+"$@"} - bootstrap_validate_options_result=$func_quote_for_eval_result -} -func_add_hook func_validate_options bootstrap_validate_options - - -## -------------------------------------------------- ## -## Source package customisations in 'bootstrap.conf'. ## -## -------------------------------------------------- ## - -# Override the default configuration, if necessary. -# Make sure that bootstrap.conf is sourced from the current directory -# if we were invoked as "sh bootstrap". -case $0 in - */*) test -r "$0.conf" && . "$0.conf" ;; - *) test -r "$0.conf" && . ./"$0.conf" ;; -esac - - -## ------------------------------- ## -## Actually perform the bootstrap. ## -## ------------------------------- ## - -func_bootstrap ${1+"$@"} - -# The End. -exit ${exit_status-$EXIT_SUCCESS} - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "500/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: diff --git a/build-aux/gl/build-aux/extract-trace b/build-aux/gl/build-aux/extract-trace deleted file mode 100755 index d0d83fe4..00000000 --- a/build-aux/gl/build-aux/extract-trace +++ /dev/null @@ -1,420 +0,0 @@ -#! /bin/sh - -# Extract macro arguments from autotools input with GNU M4. -# Written by Gary V. Vaughan, 2010 -# -# Copyright (C) 2010-2014, 2017 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# Make sure we've evaluated scripts we depend on. -test -z "$progpath" && . `echo "$0" |${SED-sed} 's|[^/]*$||'`/funclib.sh -test extract-trace = "$progname" && . `echo "$0" |${SED-sed} 's|[^/]*$||'`/options-parser - -# Set a version string. -scriptversion=2014-01-04.01; # UTC - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Please report bugs or propose patches to gary@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# Run './extract-trace --help' for help with using this script from the -# command line. -# -# Or source first 'options-parser' and then this file into your own -# scripts in order to make use of the function and variable framework -# they define, and also to avoid the overhead of forking to run this -# script in its own process on every call. - - - -## ----------------- ## -## Helper functions. ## -## ----------------- ## - -# This section contains the helper functions used by the rest of -# 'extract-trace'. - - -# func_autoconf_configure MAYBE-CONFIGURE-FILE -# -------------------------------------------- -# Ensure that MAYBE-CONFIGURE-FILE is the name of a file in the current -# directory that contains an uncommented call to AC_INIT. -func_autoconf_configure () -{ - $debug_cmd - - _G_sed_no_comment=' - s|#.*$|| - s|^dnl .*$|| - s| dnl .*$||' - _G_ac_init= - - # If we were passed a genuine file, make sure it calls AC_INIT. - test -f "$1" \ - && _G_ac_init=`$SED "$_G_sed_no_comment" "$1" |$GREP AC_INIT` - - # Otherwise it is not a genuine Autoconf input file. - test -n "$_G_ac_init" - _G_status=$? - - test 0 -ne "$_G_status" \ - && func_verbose "'$1' not using Autoconf" - - (exit $_G_status) -} - - -# func_find_tool ENVVAR NAMES... -# ------------------------------ -# Search for a required program. Use the value of ENVVAR, if set, -# otherwise find the first of the NAMES that can be run (i.e., -# supports --version). If found, set ENVVAR to the program name, -# die otherwise. -func_find_tool () -{ - $debug_cmd - - _G_find_tool_envvar=$1 - shift - _G_find_tool_names=$@ - eval "_G_find_tool_res=\$$_G_find_tool_envvar" - if test -n "$_G_find_tool_res"; then - _G_find_tool_error_prefix="\$$find_tool_envvar: " - else - for _G_prog - do - if func_tool_version_output $_G_prog >/dev/null; then - _G_find_tool_res=$_G_prog - break - fi - done - fi - if test -n "$_G_find_tool_res"; then - func_tool_version_output >/dev/null $_G_find_tool_res "\ -${_G_find_tool_error_prefix}Cannot run '$_G_find_tool_res --version'" - - # Make sure the result is exported to the environment for children - # to use. - eval "$_G_find_tool_envvar=\$_G_find_tool_res" - eval "export $_G_find_tool_envvar" - else - func_error "\ -One of these is required: - $_G_find_tool_names" - fi -} - - -# func_tool_version_output CMD [FATAL-ERROR-MSG] -# ---------------------------------------------- -# Attempt to run 'CMD --version', discarding errors. The output can be -# ignored by redirecting stdout, and this function used simply to test -# whether the command exists and exits normally when passed a -# '--version' argument. -# When FATAL-ERROR-MSG is given, then this function will display the -# message and exit if running 'CMD --version' returns a non-zero exit -# status. -func_tool_version_output () -{ - $debug_cmd - - _G_cmd=$1 - _G_fatal_error_msg=$2 - - # Some tools, like 'git2cl' produce thousands of lines of output - # unless stdin is /dev/null - in that case we want to return - # successfully without saving all of that output. Other tools, - # such as 'help2man' exit with a non-zero status when stdin comes - # from /dev/null, so we re-execute without /dev/null if that - # happens. This means that occasionally, the output from both calls - # ends up in the result, but the alternative would be to discard the - # output from one call, and hope the other produces something useful. - { $_G_cmd --version /dev/null - _G_status=$? - - test 0 -ne "$_G_status" && test -n "$_G_fatal_error_msg" \ - && func_fatal_error "$_G_fatal_error_msg" - - (exit $_G_status) -} - - -## -------------------- ## -## Resource management. ## -## -------------------- ## - -# This section contains definitions for functions that each ensure a -# particular resource (a file, or a non-empty configuration variable for -# example) is available, and if appropriate to extract default values -# from pertinent package files. Where a variable already has a non- -# empty value (as set by the package's 'bootstrap.conf'), that value is -# used in preference to deriving the default. Call them using their -# associated 'require_*' variable to ensure that they are executed, at -# most, once. -# -# It's entirely deliberate that calling these functions can set -# variables that don't obey the namespace limitations obeyed by the rest -# of this file, in order that that they be as useful as possible to -# callers. - - -# require_configure_ac -# -------------------- -# Ensure that there is a 'configure.ac' or 'configure.in' file in the -# current directory that contains an uncommented call to AC_INIT, and -# that '$configure_ac' contains its name. -require_configure_ac=func_require_configure_ac -func_require_configure_ac () -{ - $debug_cmd - - test -z "$configure_ac" \ - && func_autoconf_configure configure.ac && configure_ac=configure.ac - test -z "$configure_ac" \ - && func_autoconf_configure configure.in && configure_ac=configure.in - test -z "$configure_ac" \ - || func_verbose "found '$configure_ac'" - - require_configure_ac=: -} - - -# require_gnu_m4 -# -------------- -# Search for GNU M4, and export it in $M4. -require_gnu_m4=func_require_gnu_m4 -func_require_gnu_m4 () -{ - $debug_cmd - - test -n "$M4" || { - # Find the first m4 binary that responds to --version. - func_find_tool M4 gm4 gnum4 m4 - } - - test -n "$M4" || func_fatal_error "\ -Please install GNU M4, or 'export M4=/path/to/gnu/m4'." - - func_verbose "export M4='$M4'" - - # Make sure the search result is visible to subshells - export M4 - - require_gnu_m4=: -} - - -## --------------- ## -## Core functions. ## -## --------------- ## - -# This section contains the high level functions used when calling this -# file as a script. 'func_extract_trace' is probably the only one that you -# won't want to replace if you source this file into your own script. - - -# func_extract_trace MACRO_NAMES [FILENAME]... -# -------------------------------------------- -# set '$func_extract_trace_result' to a colon delimited list of arguments -# to any of the comma separated list of MACRO_NAMES in FILENAME. If no -# FILENAME is given, then '$configure_ac' is assumed. -func_extract_trace () -{ - $debug_cmd - - $require_configure_ac - $require_gnu_m4 - - _G_m4_traces=`$ECHO "--trace=$1" |$SED 's%,% --trace=%g'` - _G_re_macros=`$ECHO "($1)" |$SED 's%,%|%g'` - _G_macros="$1"; shift - test $# -gt 0 || { - set dummy $configure_ac - shift - } - - # Generate an error if the first file is missing - <"$1" - - # Sadly, we can't use 'autom4te' tracing to extract macro arguments, - # because it complains about things we want to ignore at bootstrap - # time - like missing m4_include files; AC_PREREQ being newer than - # the installed autoconf; and returns nothing when tracing - # 'AM_INIT_AUTOMAKE' when aclocal hasn't been generated yet. - # - # The following tries to emulate a less persnickety version of (and - # due to not having to wait for Perl startup on every invocation, - # it's probably faster too): - # - # autom4te --language=Autoconf --trace=$my_macro:\$% "$@" - # - # First we give a minimal set of macro declarations to M4 to prime - # it for reading Autoconf macros, while still providing some of the - # functionality generally used at m4-time to supply dynamic - # arguments to Autocof functions, but without following - # 'm4_s?include' files. - _G_mini=' - # Initialisation. - m4_changequote([,]) - m4_define([m4_copy], [m4_define([$2], m4_defn([$1]))]) - m4_define([m4_rename], [m4_copy([$1], [$2])m4_undefine([$1])]) - - # Disable these macros. - m4_undefine([m4_dnl]) - m4_undefine([m4_include]) - m4_undefine([m4_m4exit]) - m4_undefine([m4_m4wrap]) - m4_undefine([m4_maketemp]) - - # Copy and rename macros not handled by "m4 --prefix". - m4_define([dnl], [m4_builtin([dnl])]) - m4_copy([m4_define], [m4_defun]) - m4_rename([m4_ifelse], [m4_if]) - m4_ifdef([m4_mkstemp], [m4_undefine([m4_mkstemp])]) - m4_rename([m4_patsubst], [m4_bpatsubst]) - m4_rename([m4_regexp], [m4_bregexp]) - - # "m4sugar.mini" - useful m4-time macros for dynamic arguments. - # If we discover packages that need more m4 macros defined in - # order to bootstrap correctly, add them here: - m4_define([m4_bmatch], - [m4_if([$#], 0, [], [$#], 1, [], [$#], 2, [$2], - [m4_if(m4_bregexp([$1], [$2]), -1, - [$0([$1], m4_shift3($@))], [$3])])]) - m4_define([m4_ifndef], [m4_ifdef([$1], [$3], [$2])]) - m4_define([m4_ifset], - [m4_ifdef([$1], [m4_ifval(m4_defn([$1]), [$2], [$3])], [$3])]) - m4_define([m4_require], [$1]) - m4_define([m4_shift3], [m4_shift(m4shift(m4shift($@)))]) - - # "autoconf.mini" - things from autoconf macros we care about. - m4_copy([m4_defun], [AC_DEFUN]) - - # Dummy definitions for the macros we want to trace. - # AM_INIT_AUTOMAKE at least produces no trace without this. - ' - - _G_save=$IFS - IFS=, - for _G_macro in $_G_macros; do - IFS=$_G_save - func_append _G_mini "AC_DEFUN([$_G_macro])$nl" - done - IFS=$_G_save - - # We discard M4's stdout, but the M4 trace output from reading our - # "autoconf.mini" followed by any other files passed to this - # function is then scanned by sed to transform it into a colon - # delimited argument list assigned to a shell variable. - _G_transform='s|#.*$||; s|^dnl .*$||; s| dnl .*$||;' - - # Unfortunately, alternation in regexp addresses doesn't work in at - # least BSD (and hence Mac OS X) sed, so we have to append a capture - # and print block for each traced macro to the sed transform script. - _G_save=$IFS - IFS=, - for _G_macro in $_G_macros; do - IFS=$_G_save - func_append _G_transform ' - /^m4trace: -1- '"$_G_macro"'/ { - s|^m4trace: -1- '"$_G_macro"'[([]*|| - s|], [[]|:|g - s|[])]*$|:| - s|\(.\):$|\1| - p - }' - done - IFS=$_G_save - - # Save the command pipeline results for further use by callers of - # this function. - func_extract_trace_result=`$ECHO "$_G_mini" \ - |$M4 -daq --prefix $_G_m4_traces - "$@" 2>&1 1>/dev/null \ - |$SED -n -e "$_G_transform"` -} - - -# func_extract_trace_first MACRO_NAMES [FILENAME]... -# -------------------------------------------------- -# Exactly like func_extract_trace, except that only the first argument -# to the first invocation of one of the comma separated MACRO_NAMES is -# returned in '$func_extract_trace_first_result'. -func_extract_trace_first () -{ - $debug_cmd - - func_extract_trace ${1+"$@"} - func_extract_trace_first_result=`$ECHO "$func_extract_trace_result" \ - |$SED -e 's|:.*$||g' -e 1q` -} - - -# func_main [ARG]... -# ------------------ -func_main () -{ - $debug_cmd - - # Configuration. - usage='$progname MACRO_NAME FILE [...]' - - long_help_message=' -The first argument to this program is the name of an autotools macro -whose arguments you want to extract by examining the files listed in the -remaining arguments using the same tool that Autoconf and Automake use, -GNU M4. - -The arguments are returned separated by colons, with each traced call -on a separate line.' - - # Option processing. - func_options "$@" - eval set dummy "$func_options_result"; shift - - # Validate remaining non-option arguments. - test $# -gt 1 \ - || func_fatal_help "not enough arguments" - - # Pass non-option arguments to extraction function. - func_extract_trace "$@" - - # Display results. - test -n "$func_extract_trace_result" \ - && $ECHO "$func_extract_trace_result" - - # The End. - exit $EXIT_SUCCESS -} - - -## --------------------------- ## -## Actually perform the trace. ## -## --------------------------- ## - -# Only call 'func_main' if this script was called directly. -test extract-trace = "$progname" && func_main "$@" - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "20/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: diff --git a/build-aux/gl/build-aux/funclib.sh b/build-aux/gl/build-aux/funclib.sh deleted file mode 100644 index fbe8b67d..00000000 --- a/build-aux/gl/build-aux/funclib.sh +++ /dev/null @@ -1,1304 +0,0 @@ -# Set a version string for this script. -scriptversion=2014-01-03.01; # UTC - -# General shell script boiler plate, and helper functions. -# Written by Gary V. Vaughan, 2004 - -# Copyright (C) 2004-2014, 2017 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. - -# As a special exception to the GNU General Public License, if you distribute -# this file as part of a program or library that is built using GNU Libtool, -# you may include this file under the same distribution terms that you use -# for the rest of that program. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNES 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 . - -# Please report bugs or propose patches to gary@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# Evaluate this file near the top of your script to gain access to -# the functions and variables defined here: -# -# . `echo "$0" | ${SED-sed} 's|[^/]*$||'`/build-aux/funclib.sh -# -# If you need to override any of the default environment variable -# settings, do that before evaluating this file. - - -## -------------------- ## -## Shell normalisation. ## -## -------------------- ## - -# Some shells need a little help to be as Bourne compatible as possible. -# Before doing anything else, make sure all that help has been provided! - -DUALCASE=1; export DUALCASE # for MKS sh -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : - emulate sh - NULLCMD=: - # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix ;; esac -fi - -# NLS nuisances: We save the old values in case they are required later. -_G_user_locale= -_G_safe_locale= -for _G_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES -do - eval "if test set = \"\${$_G_var+set}\"; then - save_$_G_var=\$$_G_var - $_G_var=C - export $_G_var - _G_user_locale=\"$_G_var=\\\$save_\$_G_var; \$_G_user_locale\" - _G_safe_locale=\"$_G_var=C; \$_G_safe_locale\" - fi" -done - -# CDPATH. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -# Make sure IFS has a sensible default -sp=' ' -nl=' -' -IFS="$sp $nl" - -# There are apparently some retarded systems that use ';' as a PATH separator! -if test "${PATH_SEPARATOR+set}" != set; then - PATH_SEPARATOR=: - (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { - (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || - PATH_SEPARATOR=';' - } -fi - - - -## ------------------------- ## -## Locate command utilities. ## -## ------------------------- ## - - -# func_executable_p FILE -# ---------------------- -# Check that FILE is an executable regular file. -func_executable_p () -{ - test -f "$1" && test -x "$1" -} - - -# func_path_progs PROGS_LIST CHECK_FUNC [PATH] -# -------------------------------------------- -# Search for either a program that responds to --version with output -# containing "GNU", or else returned by CHECK_FUNC otherwise, by -# trying all the directories in PATH with each of the elements of -# PROGS_LIST. -# -# CHECK_FUNC should accept the path to a candidate program, and -# set $func_check_prog_result if it truncates its output less than -# $_G_path_prog_max characters. -func_path_progs () -{ - _G_progs_list=$1 - _G_check_func=$2 - _G_PATH=${3-"$PATH"} - - _G_path_prog_max=0 - _G_path_prog_found=false - _G_save_IFS=$IFS; IFS=$PATH_SEPARATOR - for _G_dir in $_G_PATH; do - IFS=$_G_save_IFS - test -z "$_G_dir" && _G_dir=. - for _G_prog_name in $_G_progs_list; do - for _exeext in '' .EXE; do - _G_path_prog=$_G_dir/$_G_prog_name$_exeext - func_executable_p "$_G_path_prog" || continue - case `"$_G_path_prog" --version 2>&1` in - *GNU*) func_path_progs_result=$_G_path_prog _G_path_prog_found=: ;; - *) $_G_check_func $_G_path_prog - func_path_progs_result=$func_check_prog_result - ;; - esac - $_G_path_prog_found && break 3 - done - done - done - IFS=$_G_save_IFS - test -z "$func_path_progs_result" && { - echo "no acceptable sed could be found in \$PATH" >&2 - exit 1 - } -} - - -# We want to be able to use the functions in this file before configure -# has figured out where the best binaries are kept, which means we have -# to search for them ourselves - except when the results are already set -# where we skip the searches. - -# Unless the user overrides by setting SED, search the path for either GNU -# sed, or the sed that truncates its output the least. -test -z "$SED" && { - _G_sed_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ - for _G_i in 1 2 3 4 5 6 7; do - _G_sed_script=$_G_sed_script$nl$_G_sed_script - done - echo "$_G_sed_script" 2>/dev/null | sed 99q >conftest.sed - _G_sed_script= - - func_check_prog_sed () - { - _G_path_prog=$1 - - _G_count=0 - printf 0123456789 >conftest.in - while : - do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo '' >> conftest.nl - "$_G_path_prog" -f conftest.sed conftest.out 2>/dev/null || break - diff conftest.out conftest.nl >/dev/null 2>&1 || break - _G_count=`expr $_G_count + 1` - if test "$_G_count" -gt "$_G_path_prog_max"; then - # Best one so far, save it but keep looking for a better one - func_check_prog_result=$_G_path_prog - _G_path_prog_max=$_G_count - fi - # 10*(2^10) chars as input seems more than enough - test 10 -lt "$_G_count" && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out - } - - func_path_progs "sed gsed" func_check_prog_sed $PATH:/usr/xpg4/bin - rm -f conftest.sed - SED=$func_path_progs_result -} - - -# Unless the user overrides by setting GREP, search the path for either GNU -# grep, or the grep that truncates its output the least. -test -z "$GREP" && { - func_check_prog_grep () - { - _G_path_prog=$1 - - _G_count=0 - _G_path_prog_max=0 - printf 0123456789 >conftest.in - while : - do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo 'GREP' >> conftest.nl - "$_G_path_prog" -e 'GREP$' -e '-(cannot match)-' conftest.out 2>/dev/null || break - diff conftest.out conftest.nl >/dev/null 2>&1 || break - _G_count=`expr $_G_count + 1` - if test "$_G_count" -gt "$_G_path_prog_max"; then - # Best one so far, save it but keep looking for a better one - func_check_prog_result=$_G_path_prog - _G_path_prog_max=$_G_count - fi - # 10*(2^10) chars as input seems more than enough - test 10 -lt "$_G_count" && break - done - rm -f conftest.in conftest.tmp conftest.nl conftest.out - } - - func_path_progs "grep ggrep" func_check_prog_grep $PATH:/usr/xpg4/bin - GREP=$func_path_progs_result -} - - -## ------------------------------- ## -## User overridable command paths. ## -## ------------------------------- ## - -# All uppercase variable names are used for environment variables. These -# variables can be overridden by the user before calling a script that -# uses them if a suitable command of that name is not already available -# in the command search PATH. - -: ${CP="cp -f"} -: ${ECHO="printf %s\n"} -: ${EGREP="$GREP -E"} -: ${FGREP="$GREP -F"} -: ${LN_S="ln -s"} -: ${MAKE="make"} -: ${MKDIR="mkdir"} -: ${MV="mv -f"} -: ${RM="rm -f"} -: ${SHELL="${CONFIG_SHELL-/bin/sh}"} - - -## -------------------- ## -## Useful sed snippets. ## -## -------------------- ## - -sed_dirname='s|/[^/]*$||' -sed_basename='s|^.*/||' - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s|\([`"$\\]\)|\\\1|g' - -# Same as above, but do not quote variable references. -sed_double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution that turns a string into a regex matching for the -# string literally. -sed_make_literal_regex='s|[].[^$\\*\/]|\\&|g' - -# Sed substitution that converts a w32 file name or path -# that contains forward slashes, into one that contains -# (escaped) backslashes. A very naive implementation. -sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' - -# Re-'\' parameter expansions in output of sed_double_quote_subst that -# were '\'-ed in input to the same. If an odd number of '\' preceded a -# '$' in input to sed_double_quote_subst, that '$' was protected from -# expansion. Since each input '\' is now two '\'s, look for any number -# of runs of four '\'s followed by two '\'s and then a '$'. '\' that '$'. -_G_bs='\\' -_G_bs2='\\\\' -_G_bs4='\\\\\\\\' -_G_dollar='\$' -sed_double_backslash="\ - s/$_G_bs4/&\\ -/g - s/^$_G_bs2$_G_dollar/$_G_bs&/ - s/\\([^$_G_bs]\\)$_G_bs2$_G_dollar/\\1$_G_bs2$_G_bs$_G_dollar/g - s/\n//g" - - -## ----------------- ## -## Global variables. ## -## ----------------- ## - -# Except for the global variables explicitly listed below, the following -# functions in the '^func_' namespace, and the '^require_' namespace -# variables initialised in the 'Resource management' section, sourcing -# this file will not pollute your global namespace with anything -# else. There's no portable way to scope variables in Bourne shell -# though, so actually running these functions will sometimes place -# results into a variable named after the function, and often use -# temporary variables in the '^_G_' namespace. If you are careful to -# avoid using those namespaces casually in your sourcing script, things -# should continue to work as you expect. And, of course, you can freely -# overwrite any of the functions or variables defined here before -# calling anything to customize them. - -EXIT_SUCCESS=0 -EXIT_FAILURE=1 -EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. -EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. - -# Allow overriding, eg assuming that you follow the convention of -# putting '$debug_cmd' at the start of all your functions, you can get -# bash to show function call trace with: -# -# debug_cmd='eval echo "${FUNCNAME[0]} $*" >&2' bash your-script-name -debug_cmd=${debug_cmd-":"} -exit_cmd=: - -# By convention, finish your script with: -# -# exit $exit_status -# -# so that you can set exit_status to non-zero if you want to indicate -# something went wrong during execution without actually bailing out at -# the point of failure. -exit_status=$EXIT_SUCCESS - -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath=$0 - -# The name of this program. -progname=`$ECHO "$progpath" |$SED "$sed_basename"` - -# Make sure we have an absolute progpath for reexecution: -case $progpath in - [\\/]*|[A-Za-z]:\\*) ;; - *[\\/]*) - progdir=`$ECHO "$progpath" |$SED "$sed_dirname"` - progdir=`cd "$progdir" && pwd` - progpath=$progdir/$progname - ;; - *) - _G_IFS=$IFS - IFS=${PATH_SEPARATOR-:} - for progdir in $PATH; do - IFS=$_G_IFS - test -x "$progdir/$progname" && break - done - IFS=$_G_IFS - test -n "$progdir" || progdir=`pwd` - progpath=$progdir/$progname - ;; -esac - - -## ----------------- ## -## Standard options. ## -## ----------------- ## - -# The following options affect the operation of the functions defined -# below, and should be set appropriately depending on run-time para- -# meters passed on the command line. - -opt_dry_run=false -opt_quiet=false -opt_verbose=false - -# Categories 'all' and 'none' are always available. Append any others -# you will pass as the first argument to func_warning from your own -# code. -warning_categories= - -# By default, display warnings according to 'opt_warning_types'. Set -# 'warning_func' to ':' to elide all warnings, or func_fatal_error to -# treat the next displayed warning as a fatal error. -warning_func=func_warn_and_continue - -# Set to 'all' to display all warnings, 'none' to suppress all -# warnings, or a space delimited list of some subset of -# 'warning_categories' to display only the listed warnings. -opt_warning_types=all - - -## -------------------- ## -## Resource management. ## -## -------------------- ## - -# This section contains definitions for functions that each ensure a -# particular resource (a file, or a non-empty configuration variable for -# example) is available, and if appropriate to extract default values -# from pertinent package files. Call them using their associated -# 'require_*' variable to ensure that they are executed, at most, once. -# -# It's entirely deliberate that calling these functions can set -# variables that don't obey the namespace limitations obeyed by the rest -# of this file, in order that that they be as useful as possible to -# callers. - - -# require_term_colors -# ------------------- -# Allow display of bold text on terminals that support it. -require_term_colors=func_require_term_colors -func_require_term_colors () -{ - $debug_cmd - - test -t 1 && { - # COLORTERM and USE_ANSI_COLORS environment variables take - # precedence, because most terminfo databases neglect to describe - # whether color sequences are supported. - test -n "${COLORTERM+set}" && : ${USE_ANSI_COLORS="1"} - - if test 1 = "$USE_ANSI_COLORS"; then - # Standard ANSI escape sequences - tc_reset='' - tc_bold=''; tc_standout='' - tc_red=''; tc_green='' - tc_blue=''; tc_cyan='' - else - # Otherwise trust the terminfo database after all. - test -n "`tput sgr0 2>/dev/null`" && { - tc_reset=`tput sgr0` - test -n "`tput bold 2>/dev/null`" && tc_bold=`tput bold` - tc_standout=$tc_bold - test -n "`tput smso 2>/dev/null`" && tc_standout=`tput smso` - test -n "`tput setaf 1 2>/dev/null`" && tc_red=`tput setaf 1` - test -n "`tput setaf 2 2>/dev/null`" && tc_green=`tput setaf 2` - test -n "`tput setaf 4 2>/dev/null`" && tc_blue=`tput setaf 4` - test -n "`tput setaf 5 2>/dev/null`" && tc_cyan=`tput setaf 5` - } - fi - } - - require_term_colors=: -} - - -## ----------------- ## -## Function library. ## -## ----------------- ## - -# This section contains a variety of useful functions to call in your -# scripts. Take note of the portable wrappers for features provided by -# some modern shells, which will fall back to slower equivalents on -# less featureful shells. - - -# func_append VAR VALUE -# --------------------- -# Append VALUE onto the existing contents of VAR. - - # We should try to minimise forks, especially on Windows where they are - # unreasonably slow, so skip the feature probes when bash or zsh are - # being used: - if test set = "${BASH_VERSION+set}${ZSH_VERSION+set}"; then - : ${_G_HAVE_ARITH_OP="yes"} - : ${_G_HAVE_XSI_OPS="yes"} - # The += operator was introduced in bash 3.1 - case $BASH_VERSION in - [12].* | 3.0 | 3.0*) ;; - *) - : ${_G_HAVE_PLUSEQ_OP="yes"} - ;; - esac - fi - - # _G_HAVE_PLUSEQ_OP - # Can be empty, in which case the shell is probed, "yes" if += is - # useable or anything else if it does not work. - test -z "$_G_HAVE_PLUSEQ_OP" \ - && (eval 'x=a; x+=" b"; test "a b" = "$x"') 2>/dev/null \ - && _G_HAVE_PLUSEQ_OP=yes - -if test yes = "$_G_HAVE_PLUSEQ_OP" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_append () - { - $debug_cmd - - eval "$1+=\$2" - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_append () - { - $debug_cmd - - eval "$1=\$$1\$2" - } -fi - - -# func_append_quoted VAR VALUE -# ---------------------------- -# Quote VALUE and append to the end of shell variable VAR, separated -# by a space. -if test yes = "$_G_HAVE_PLUSEQ_OP"; then - eval 'func_append_quoted () - { - $debug_cmd - - func_quote_for_eval "$2" - eval "$1+=\\ \$func_quote_for_eval_result" - }' -else - func_append_quoted () - { - $debug_cmd - - func_quote_for_eval "$2" - eval "$1=\$$1\\ \$func_quote_for_eval_result" - } -fi - - -# func_append_uniq VAR VALUE -# -------------------------- -# Append unique VALUE onto the existing contents of VAR, assuming -# entries are delimited by the first character of VALUE. For example: -# -# func_append_uniq options " --another-option option-argument" -# -# will only append to $options if " --another-option option-argument " -# is not already present somewhere in $options already (note spaces at -# each end implied by leading space in second argument). -func_append_uniq () -{ - $debug_cmd - - eval _G_current_value='`$ECHO $'$1'`' - _G_delim=`expr "$2" : '\(.\)'` - - case $_G_delim$_G_current_value$_G_delim in - *"$2$_G_delim"*) ;; - *) func_append "$@" ;; - esac -} - - -# func_arith TERM... -# ------------------ -# Set func_arith_result to the result of evaluating TERMs. - test -z "$_G_HAVE_ARITH_OP" \ - && (eval 'test 2 = $(( 1 + 1 ))') 2>/dev/null \ - && _G_HAVE_ARITH_OP=yes - -if test yes = "$_G_HAVE_ARITH_OP"; then - eval 'func_arith () - { - $debug_cmd - - func_arith_result=$(( $* )) - }' -else - func_arith () - { - $debug_cmd - - func_arith_result=`expr "$@"` - } -fi - - -# func_basename FILE -# ------------------ -# Set func_basename_result to FILE with everything up to and including -# the last / stripped. -if test yes = "$_G_HAVE_XSI_OPS"; then - # If this shell supports suffix pattern removal, then use it to avoid - # forking. Hide the definitions single quotes in case the shell chokes - # on unsupported syntax... - _b='func_basename_result=${1##*/}' - _d='case $1 in - */*) func_dirname_result=${1%/*}$2 ;; - * ) func_dirname_result=$3 ;; - esac' - -else - # ...otherwise fall back to using sed. - _b='func_basename_result=`$ECHO "$1" |$SED "$sed_basename"`' - _d='func_dirname_result=`$ECHO "$1" |$SED "$sed_dirname"` - if test "X$func_dirname_result" = "X$1"; then - func_dirname_result=$3 - else - func_append func_dirname_result "$2" - fi' -fi - -eval 'func_basename () -{ - $debug_cmd - - '"$_b"' -}' - - -# func_dirname FILE APPEND NONDIR_REPLACEMENT -# ------------------------------------------- -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -eval 'func_dirname () -{ - $debug_cmd - - '"$_d"' -}' - - -# func_dirname_and_basename FILE APPEND NONDIR_REPLACEMENT -# -------------------------------------------------------- -# Perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# For efficiency, we do not delegate to the functions above but instead -# duplicate the functionality here. -eval 'func_dirname_and_basename () -{ - $debug_cmd - - '"$_b"' - '"$_d"' -}' - - -# func_echo ARG... -# ---------------- -# Echo program name prefixed message. -func_echo () -{ - $debug_cmd - - _G_message=$* - - func_echo_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_IFS - $ECHO "$progname: $_G_line" - done - IFS=$func_echo_IFS -} - - -# func_echo_all ARG... -# -------------------- -# Invoke $ECHO with all args, space-separated. -func_echo_all () -{ - $ECHO "$*" -} - - -# func_echo_infix_1 INFIX ARG... -# ------------------------------ -# Echo program name, followed by INFIX on the first line, with any -# additional lines not showing INFIX. -func_echo_infix_1 () -{ - $debug_cmd - - $require_term_colors - - _G_infix=$1; shift - _G_indent=$_G_infix - _G_prefix="$progname: $_G_infix: " - _G_message=$* - - # Strip color escape sequences before counting printable length - for _G_tc in "$tc_reset" "$tc_bold" "$tc_standout" "$tc_red" "$tc_green" "$tc_blue" "$tc_cyan" - do - test -n "$_G_tc" && { - _G_esc_tc=`$ECHO "$_G_tc" | $SED "$sed_make_literal_regex"` - _G_indent=`$ECHO "$_G_indent" | $SED "s|$_G_esc_tc||g"` - } - done - _G_indent="$progname: "`echo "$_G_indent" | $SED 's|.| |g'`" " ## exclude from sc_prohibit_nested_quotes - - func_echo_infix_1_IFS=$IFS - IFS=$nl - for _G_line in $_G_message; do - IFS=$func_echo_infix_1_IFS - $ECHO "$_G_prefix$tc_bold$_G_line$tc_reset" >&2 - _G_prefix=$_G_indent - done - IFS=$func_echo_infix_1_IFS -} - - -# func_error ARG... -# ----------------- -# Echo program name prefixed message to standard error. -func_error () -{ - $debug_cmd - - $require_term_colors - - func_echo_infix_1 " $tc_standout${tc_red}error$tc_reset" "$*" >&2 -} - - -# func_fatal_error ARG... -# ----------------------- -# Echo program name prefixed message to standard error, and exit. -func_fatal_error () -{ - $debug_cmd - - func_error "$*" - exit $EXIT_FAILURE -} - - -# func_grep EXPRESSION FILENAME -# ----------------------------- -# Check whether EXPRESSION matches any line of FILENAME, without output. -func_grep () -{ - $debug_cmd - - $GREP "$1" "$2" >/dev/null 2>&1 -} - - -# func_len STRING -# --------------- -# Set func_len_result to the length of STRING. STRING may not -# start with a hyphen. - test -z "$_G_HAVE_XSI_OPS" \ - && (eval 'x=a/b/c; - test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ - && _G_HAVE_XSI_OPS=yes - -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_len () - { - $debug_cmd - - func_len_result=${#1} - }' -else - func_len () - { - $debug_cmd - - func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` - } -fi - - -# func_mkdir_p DIRECTORY-PATH -# --------------------------- -# Make sure the entire path to DIRECTORY-PATH is available. -func_mkdir_p () -{ - $debug_cmd - - _G_directory_path=$1 - _G_dir_list= - - if test -n "$_G_directory_path" && test : != "$opt_dry_run"; then - - # Protect directory names starting with '-' - case $_G_directory_path in - -*) _G_directory_path=./$_G_directory_path ;; - esac - - # While some portion of DIR does not yet exist... - while test ! -d "$_G_directory_path"; do - # ...make a list in topmost first order. Use a colon delimited - # list incase some portion of path contains whitespace. - _G_dir_list=$_G_directory_path:$_G_dir_list - - # If the last portion added has no slash in it, the list is done - case $_G_directory_path in */*) ;; *) break ;; esac - - # ...otherwise throw away the child directory and loop - _G_directory_path=`$ECHO "$_G_directory_path" | $SED -e "$sed_dirname"` - done - _G_dir_list=`$ECHO "$_G_dir_list" | $SED 's|:*$||'` - - func_mkdir_p_IFS=$IFS; IFS=: - for _G_dir in $_G_dir_list; do - IFS=$func_mkdir_p_IFS - # mkdir can fail with a 'File exist' error if two processes - # try to create one of the directories concurrently. Don't - # stop in that case! - $MKDIR "$_G_dir" 2>/dev/null || : - done - IFS=$func_mkdir_p_IFS - - # Bail out if we (or some other process) failed to create a directory. - test -d "$_G_directory_path" || \ - func_fatal_error "Failed to create '$1'" - fi -} - - -# func_mktempdir [BASENAME] -# ------------------------- -# Make a temporary directory that won't clash with other running -# libtool processes, and avoids race conditions if possible. If -# given, BASENAME is the basename for that directory. -func_mktempdir () -{ - $debug_cmd - - _G_template=${TMPDIR-/tmp}/${1-$progname} - - if test : = "$opt_dry_run"; then - # Return a directory name, but don't create it in dry-run mode - _G_tmpdir=$_G_template-$$ - else - - # If mktemp works, use that first and foremost - _G_tmpdir=`mktemp -d "$_G_template-XXXXXXXX" 2>/dev/null` - - if test ! -d "$_G_tmpdir"; then - # Failing that, at least try and use $RANDOM to avoid a race - _G_tmpdir=$_G_template-${RANDOM-0}$$ - - func_mktempdir_umask=`umask` - umask 0077 - $MKDIR "$_G_tmpdir" - umask $func_mktempdir_umask - fi - - # If we're not in dry-run mode, bomb out on failure - test -d "$_G_tmpdir" || \ - func_fatal_error "cannot create temporary directory '$_G_tmpdir'" - fi - - $ECHO "$_G_tmpdir" -} - - -# func_normal_abspath PATH -# ------------------------ -# Remove doubled-up and trailing slashes, "." path components, -# and cancel out any ".." path components in PATH after making -# it an absolute path. -func_normal_abspath () -{ - $debug_cmd - - # These SED scripts presuppose an absolute path with a trailing slash. - _G_pathcar='s|^/\([^/]*\).*$|\1|' - _G_pathcdr='s|^/[^/]*||' - _G_removedotparts=':dotsl - s|/\./|/|g - t dotsl - s|/\.$|/|' - _G_collapseslashes='s|/\{1,\}|/|g' - _G_finalslash='s|/*$|/|' - - # Start from root dir and reassemble the path. - func_normal_abspath_result= - func_normal_abspath_tpath=$1 - func_normal_abspath_altnamespace= - case $func_normal_abspath_tpath in - "") - # Empty path, that just means $cwd. - func_stripname '' '/' "`pwd`" - func_normal_abspath_result=$func_stripname_result - return - ;; - # The next three entries are used to spot a run of precisely - # two leading slashes without using negated character classes; - # we take advantage of case's first-match behaviour. - ///*) - # Unusual form of absolute path, do nothing. - ;; - //*) - # Not necessarily an ordinary path; POSIX reserves leading '//' - # and for example Cygwin uses it to access remote file shares - # over CIFS/SMB, so we conserve a leading double slash if found. - func_normal_abspath_altnamespace=/ - ;; - /*) - # Absolute path, do nothing. - ;; - *) - # Relative path, prepend $cwd. - func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath - ;; - esac - - # Cancel out all the simple stuff to save iterations. We also want - # the path to end with a slash for ease of parsing, so make sure - # there is one (and only one) here. - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_removedotparts" -e "$_G_collapseslashes" -e "$_G_finalslash"` - while :; do - # Processed it all yet? - if test / = "$func_normal_abspath_tpath"; then - # If we ascended to the root using ".." the result may be empty now. - if test -z "$func_normal_abspath_result"; then - func_normal_abspath_result=/ - fi - break - fi - func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_pathcar"` - func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ - -e "$_G_pathcdr"` - # Figure out what to do with it - case $func_normal_abspath_tcomponent in - "") - # Trailing empty path component, ignore it. - ;; - ..) - # Parent dir; strip last assembled component from result. - func_dirname "$func_normal_abspath_result" - func_normal_abspath_result=$func_dirname_result - ;; - *) - # Actual path component, append it. - func_append func_normal_abspath_result "/$func_normal_abspath_tcomponent" - ;; - esac - done - # Restore leading double-slash if one was found on entry. - func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result -} - - -# func_notquiet ARG... -# -------------------- -# Echo program name prefixed message only when not in quiet mode. -func_notquiet () -{ - $debug_cmd - - $opt_quiet || func_echo ${1+"$@"} - - # A bug in bash halts the script if the last line of a function - # fails when set -e is in force, so we need another command to - # work around that: - : -} - - -# func_relative_path SRCDIR DSTDIR -# -------------------------------- -# Set func_relative_path_result to the relative path from SRCDIR to DSTDIR. -func_relative_path () -{ - $debug_cmd - - func_relative_path_result= - func_normal_abspath "$1" - func_relative_path_tlibdir=$func_normal_abspath_result - func_normal_abspath "$2" - func_relative_path_tbindir=$func_normal_abspath_result - - # Ascend the tree starting from libdir - while :; do - # check if we have found a prefix of bindir - case $func_relative_path_tbindir in - $func_relative_path_tlibdir) - # found an exact match - func_relative_path_tcancelled= - break - ;; - $func_relative_path_tlibdir*) - # found a matching prefix - func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" - func_relative_path_tcancelled=$func_stripname_result - if test -z "$func_relative_path_result"; then - func_relative_path_result=. - fi - break - ;; - *) - func_dirname $func_relative_path_tlibdir - func_relative_path_tlibdir=$func_dirname_result - if test -z "$func_relative_path_tlibdir"; then - # Have to descend all the way to the root! - func_relative_path_result=../$func_relative_path_result - func_relative_path_tcancelled=$func_relative_path_tbindir - break - fi - func_relative_path_result=../$func_relative_path_result - ;; - esac - done - - # Now calculate path; take care to avoid doubling-up slashes. - func_stripname '' '/' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - func_stripname '/' '/' "$func_relative_path_tcancelled" - if test -n "$func_stripname_result"; then - func_append func_relative_path_result "/$func_stripname_result" - fi - - # Normalisation. If bindir is libdir, return '.' else relative path. - if test -n "$func_relative_path_result"; then - func_stripname './' '' "$func_relative_path_result" - func_relative_path_result=$func_stripname_result - fi - - test -n "$func_relative_path_result" || func_relative_path_result=. - - : -} - - -# func_quote_for_eval ARG... -# -------------------------- -# Aesthetically quote ARGs to be evaled later. -# This function returns two values: -# i) func_quote_for_eval_result -# double-quoted, suitable for a subsequent eval -# ii) func_quote_for_eval_unquoted_result -# has all characters that are still active within double -# quotes backslashified. -func_quote_for_eval () -{ - $debug_cmd - - func_quote_for_eval_unquoted_result= - func_quote_for_eval_result= - while test 0 -lt $#; do - case $1 in - *[\\\`\"\$]*) - _G_unquoted_arg=`printf '%s\n' "$1" |$SED "$sed_quote_subst"` ;; - *) - _G_unquoted_arg=$1 ;; - esac - if test -n "$func_quote_for_eval_unquoted_result"; then - func_append func_quote_for_eval_unquoted_result " $_G_unquoted_arg" - else - func_append func_quote_for_eval_unquoted_result "$_G_unquoted_arg" - fi - - case $_G_unquoted_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting, command substitution and variable expansion - # for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - _G_quoted_arg=\"$_G_unquoted_arg\" - ;; - *) - _G_quoted_arg=$_G_unquoted_arg - ;; - esac - - if test -n "$func_quote_for_eval_result"; then - func_append func_quote_for_eval_result " $_G_quoted_arg" - else - func_append func_quote_for_eval_result "$_G_quoted_arg" - fi - shift - done -} - - -# func_quote_for_expand ARG -# ------------------------- -# Aesthetically quote ARG to be evaled later; same as above, -# but do not quote variable references. -func_quote_for_expand () -{ - $debug_cmd - - case $1 in - *[\\\`\"]*) - _G_arg=`$ECHO "$1" | $SED \ - -e "$sed_double_quote_subst" -e "$sed_double_backslash"` ;; - *) - _G_arg=$1 ;; - esac - - case $_G_arg in - # Double-quote args containing shell metacharacters to delay - # word splitting and command substitution for a subsequent eval. - # Many Bourne shells cannot handle close brackets correctly - # in scan sets, so we specify it separately. - *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") - _G_arg=\"$_G_arg\" - ;; - esac - - func_quote_for_expand_result=$_G_arg -} - - -# func_stripname PREFIX SUFFIX NAME -# --------------------------------- -# strip PREFIX and SUFFIX from NAME, and store in func_stripname_result. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -if test yes = "$_G_HAVE_XSI_OPS"; then - eval 'func_stripname () - { - $debug_cmd - - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary variable first. - func_stripname_result=$3 - func_stripname_result=${func_stripname_result#"$1"} - func_stripname_result=${func_stripname_result%"$2"} - }' -else - func_stripname () - { - $debug_cmd - - case $2 in - .*) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%\\\\$2\$%%"`;; - *) func_stripname_result=`$ECHO "$3" | $SED -e "s%^$1%%" -e "s%$2\$%%"`;; - esac - } -fi - - -# func_show_eval CMD [FAIL_EXP] -# ----------------------------- -# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. -func_show_eval () -{ - $debug_cmd - - _G_cmd=$1 - _G_fail_exp=${2-':'} - - func_quote_for_expand "$_G_cmd" - eval "func_notquiet $func_quote_for_expand_result" - - $opt_dry_run || { - eval "$_G_cmd" - _G_status=$? - if test 0 -ne "$_G_status"; then - eval "(exit $_G_status); $_G_fail_exp" - fi - } -} - - -# func_show_eval_locale CMD [FAIL_EXP] -# ------------------------------------ -# Unless opt_quiet is true, then output CMD. Then, if opt_dryrun is -# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP -# is given, then evaluate it. Use the saved locale for evaluation. -func_show_eval_locale () -{ - $debug_cmd - - _G_cmd=$1 - _G_fail_exp=${2-':'} - - $opt_quiet || { - func_quote_for_expand "$_G_cmd" - eval "func_echo $func_quote_for_expand_result" - } - - $opt_dry_run || { - eval "$_G_user_locale - $_G_cmd" - _G_status=$? - eval "$_G_safe_locale" - if test 0 -ne "$_G_status"; then - eval "(exit $_G_status); $_G_fail_exp" - fi - } -} - - -# func_tr_sh -# ---------- -# Turn $1 into a string suitable for a shell variable name. -# Result is stored in $func_tr_sh_result. All characters -# not in the set a-zA-Z0-9_ are replaced with '_'. Further, -# if $1 begins with a digit, a '_' is prepended as well. -func_tr_sh () -{ - $debug_cmd - - case $1 in - [0-9]* | *[!a-zA-Z0-9_]*) - func_tr_sh_result=`$ECHO "$1" | $SED -e 's/^\([0-9]\)/_\1/' -e 's/[^a-zA-Z0-9_]/_/g'` - ;; - * ) - func_tr_sh_result=$1 - ;; - esac -} - - -# func_verbose ARG... -# ------------------- -# Echo program name prefixed message in verbose mode only. -func_verbose () -{ - $debug_cmd - - $opt_verbose && func_echo "$*" - - : -} - - -# func_warn_and_continue ARG... -# ----------------------------- -# Echo program name prefixed warning message to standard error. -func_warn_and_continue () -{ - $debug_cmd - - $require_term_colors - - func_echo_infix_1 "${tc_red}warning$tc_reset" "$*" >&2 -} - - -# func_warning CATEGORY ARG... -# ---------------------------- -# Echo program name prefixed warning message to standard error. Warning -# messages can be filtered according to CATEGORY, where this function -# elides messages where CATEGORY is not listed in the global variable -# 'opt_warning_types'. -func_warning () -{ - $debug_cmd - - # CATEGORY must be in the warning_categories list! - case " $warning_categories " in - *" $1 "*) ;; - *) func_internal_error "invalid warning category '$1'" ;; - esac - - _G_category=$1 - shift - - case " $opt_warning_types " in - *" $_G_category "*) $warning_func ${1+"$@"} ;; - esac -} - - -# func_sort_ver VER1 VER2 -# ----------------------- -# 'sort -V' is not generally available. -# Note this deviates from the version comparison in automake -# in that it treats 1.5 < 1.5.0, and treats 1.4.4a < 1.4-p3a -# but this should suffice as we won't be specifying old -# version formats or redundant trailing .0 in bootstrap.conf. -# If we did want full compatibility then we should probably -# use m4_version_compare from autoconf. -func_sort_ver () -{ - $debug_cmd - - printf '%s\n%s\n' "$1" "$2" \ - | sort -t. -k 1,1n -k 2,2n -k 3,3n -k 4,4n -k 5,5n -k 6,6n -k 7,7n -k 8,8n -k 9,9n -} - -# func_lt_ver PREV CURR -# --------------------- -# Return true if PREV and CURR are in the correct order according to -# func_sort_ver, otherwise false. Use it like this: -# -# func_lt_ver "$prev_ver" "$proposed_ver" || func_fatal_error "..." -func_lt_ver () -{ - $debug_cmd - - test "x$1" = x`func_sort_ver "$1" "$2" | $SED 1q` -} - - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: diff --git a/build-aux/gl/build-aux/inline-source b/build-aux/gl/build-aux/inline-source deleted file mode 100755 index 0e4da9c4..00000000 --- a/build-aux/gl/build-aux/inline-source +++ /dev/null @@ -1,164 +0,0 @@ -#! /bin/sh - -# Output the contents of a shell script with sourced files inlined. -# Written by Gary V. Vaughan, 2012 - -# Copyright (C) 2012-2014, 2017 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# Source required external libraries: -. `echo "$0" |${SED-sed} 's|[^/]*$||'`"funclib.sh" -. `echo "$0" |${SED-sed} 's|[^/]*$||'`"options-parser" - -# Set a version string for *this* script. -scriptversion=2014-01-03.01; # UTC - - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Please report bugs or propose patches to bug-libtool@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# Run 'build-aux/inline-source --help' for help with using this script -# from the command line. - -# Recursively scan through a FILE passed on the command line, replacing -# either of the following: -# . "relative/file" -# . `echo "$0" |edit`"relative/file" -# with the contents of the referenced files. - - -## ---------------- ## -## Options parsing. ## -## ---------------- ## - -usage='$progpath [OPTION]... FILE' - -# Short help message in response to '-h'. -usage_message='Options: - --debug enable verbose shell tracing - --version print version information and exit - -h, --help print help message and exit -' - -long_help_message="\ -Report bugs to -General help using GNU software: ." - -func_options ${1+"$@"} -eval set dummy "$func_options_result"; shift - - -## -------------------- ## -## Resource management. ## -## -------------------- ## - -# require_AWK -# ----------- -# Search for a "not hopeless" awk. -require_AWK=func_require_AWK -func_require_AWK () -{ - $debug_cmd - - test -n "$AWK" || { - # Find the first executable in the list. - for _G_prog in gawk mawk nawk awk - do - require_AWK_IFS=$IFS - IFS=${PATH_SEPARATOR-:} - for _G_dir in $PATH - do - IFS=$require_AWK_IFS - if test -f "$_G_dir/$_G_prog" && test -x "$_G_dir/$_G_prog" - then - AWK=$_G_dir/$_G_prog - break 2 - fi - done - IFS=$require_AWK_IFS - done - } - - test -n "$AWK" || func_fatal_error "\ -Please install GNU Awk, or 'export AWK=/path/to/gnu/awk'." - - func_verbose "found '$AWK'." - - require_AWK=: -} - - -## --------------- ## -## Core functions. ## -## --------------- ## - -# func_include LINE -# ----------------- -# Output the contents of file included by LINE. -func_include () -{ - $require_AWK - - test -f "$1" \ - || func_fatal_error "file '$1' not found" - - _G_scriptdir=`echo "$1" |$SED 's|[^/]*$||'` - test -n "$_G_scriptdir" || _G_scriptdir="./" - - $AWK ' - BEGIN { magic = '${_RECURSE_MAGIC-0}'; } - - /^#!/ && magic == 0 { - print $0; - print "## DO NOT EDIT - This file generated from '$1'"; - print "## by '$progname' v'$scriptversion'"; - magic++; - next; - } - - /^\. ['\''"].*['\''"]$/ { - file = substr ($2, 2, length ($2) -2); - system (sprintf ("env _RECURSE_MAGIC=%d '$progpath' %s", magic, file)); - next; - } - - /^\. `echo [^`]*`['\''"][^'\''"]*['\''"]$/ { - tail = substr ($0, match ($0, /`['\''"]/)); - file = substr (tail, 3, length (tail) -3); - system (sprintf ("env _RECURSE_MAGIC=%d '$progpath' '"$_G_scriptdir"'%s", magic, file)); - next; - } - - { print; } - ' < "$1" -} - -func_include "$1" - -exit 0 - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "20/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: diff --git a/build-aux/gl/build-aux/options-parser b/build-aux/gl/build-aux/options-parser deleted file mode 100644 index dd9867f2..00000000 --- a/build-aux/gl/build-aux/options-parser +++ /dev/null @@ -1,608 +0,0 @@ -#! /bin/sh - -# Set a version string for this script. -scriptversion=2014-01-07.03; # UTC - -# A portable, pluggable option parser for Bourne shell. -# Written by Gary V. Vaughan, 2010 - -# Copyright (C) 2010-2014, 2017 Free Software Foundation, Inc. -# This is free software; see the source for copying conditions. There is NO -# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# Please report bugs or propose patches to gary@gnu.org. - - -## ------ ## -## Usage. ## -## ------ ## - -# This file is a library for parsing options in your shell scripts along -# with assorted other useful supporting features that you can make use -# of too. -# -# For the simplest scripts you might need only: -# -# #!/bin/sh -# . relative/path/to/funclib.sh -# . relative/path/to/options-parser -# scriptversion=1.0 -# func_options ${1+"$@"} -# eval set dummy "$func_options_result"; shift -# ...rest of your script... -# -# In order for the '--version' option to work, you will need to have a -# suitably formatted comment like the one at the top of this file -# starting with '# Written by ' and ending with '# warranty; '. -# -# For '-h' and '--help' to work, you will also need a one line -# description of your script's purpose in a comment directly above the -# '# Written by ' line, like the one at the top of this file. -# -# The default options also support '--debug', which will turn on shell -# execution tracing (see the comment above debug_cmd below for another -# use), and '--verbose' and the func_verbose function to allow your script -# to display verbose messages only when your user has specified -# '--verbose'. -# -# After sourcing this file, you can plug processing for additional -# options by amending the variables from the 'Configuration' section -# below, and following the instructions in the 'Option parsing' -# section further down. - -## -------------- ## -## Configuration. ## -## -------------- ## - -# You should override these variables in your script after sourcing this -# file so that they reflect the customisations you have added to the -# option parser. - -# The usage line for option parsing errors and the start of '-h' and -# '--help' output messages. You can embed shell variables for delayed -# expansion at the time the message is displayed, but you will need to -# quote other shell meta-characters carefully to prevent them being -# expanded when the contents are evaled. -usage='$progpath [OPTION]...' - -# Short help message in response to '-h' and '--help'. Add to this or -# override it after sourcing this library to reflect the full set of -# options your script accepts. -usage_message="\ - --debug enable verbose shell tracing - -W, --warnings=CATEGORY - report the warnings falling in CATEGORY [all] - -v, --verbose verbosely report processing - --version print version information and exit - -h, --help print short or long help message and exit -" - -# Additional text appended to 'usage_message' in response to '--help'. -long_help_message=" -Warning categories include: - 'all' show all warnings - 'none' turn off all the warnings - 'error' warnings are treated as fatal errors" - -# Help message printed before fatal option parsing errors. -fatal_help="Try '\$progname --help' for more information." - - - -## ------------------------- ## -## Hook function management. ## -## ------------------------- ## - -# This section contains functions for adding, removing, and running hooks -# to the main code. A hook is just a named list of of function, that can -# be run in order later on. - -# func_hookable FUNC_NAME -# ----------------------- -# Declare that FUNC_NAME will run hooks added with -# 'func_add_hook FUNC_NAME ...'. -func_hookable () -{ - $debug_cmd - - func_append hookable_fns " $1" -} - - -# func_add_hook FUNC_NAME HOOK_FUNC -# --------------------------------- -# Request that FUNC_NAME call HOOK_FUNC before it returns. FUNC_NAME must -# first have been declared "hookable" by a call to 'func_hookable'. -func_add_hook () -{ - $debug_cmd - - case " $hookable_fns " in - *" $1 "*) ;; - *) func_fatal_error "'$1' does not accept hook functions." ;; - esac - - eval func_append ${1}_hooks '" $2"' -} - - -# func_remove_hook FUNC_NAME HOOK_FUNC -# ------------------------------------ -# Remove HOOK_FUNC from the list of functions called by FUNC_NAME. -func_remove_hook () -{ - $debug_cmd - - eval ${1}_hooks='`$ECHO "\$'$1'_hooks" |$SED "s| '$2'||"`' -} - - -# func_run_hooks FUNC_NAME [ARG]... -# --------------------------------- -# Run all hook functions registered to FUNC_NAME. -# It is assumed that the list of hook functions contains nothing more -# than a whitespace-delimited list of legal shell function names, and -# no effort is wasted trying to catch shell meta-characters or preserve -# whitespace. -func_run_hooks () -{ - $debug_cmd - - case " $hookable_fns " in - *" $1 "*) ;; - *) func_fatal_error "'$1' does not support hook funcions.n" ;; - esac - - eval _G_hook_fns=\$$1_hooks; shift - - for _G_hook in $_G_hook_fns; do - eval $_G_hook '"$@"' - - # store returned options list back into positional - # parameters for next 'cmd' execution. - eval _G_hook_result=\$${_G_hook}_result - eval set dummy "$_G_hook_result"; shift - done - - func_quote_for_eval ${1+"$@"} - func_run_hooks_result=$func_quote_for_eval_result -} - - - -## --------------- ## -## Option parsing. ## -## --------------- ## - -# In order to add your own option parsing hooks, you must accept the -# full positional parameter list in your hook function, remove any -# options that you action, and then pass back the remaining unprocessed -# options in '_result', escaped suitably for -# 'eval'. Like this: -# -# my_options_prep () -# { -# $debug_cmd -# -# # Extend the existing usage message. -# usage_message=$usage_message' -# -s, --silent don'\''t print informational messages -# ' -# -# func_quote_for_eval ${1+"$@"} -# my_options_prep_result=$func_quote_for_eval_result -# } -# func_add_hook func_options_prep my_options_prep -# -# -# my_silent_option () -# { -# $debug_cmd -# -# # Note that for efficiency, we parse as many options as we can -# # recognise in a loop before passing the remainder back to the -# # caller on the first unrecognised argument we encounter. -# while test $# -gt 0; do -# opt=$1; shift -# case $opt in -# --silent|-s) opt_silent=: ;; -# # Separate non-argument short options: -# -s*) func_split_short_opt "$_G_opt" -# set dummy "$func_split_short_opt_name" \ -# "-$func_split_short_opt_arg" ${1+"$@"} -# shift -# ;; -# *) set dummy "$_G_opt" "$*"; shift; break ;; -# esac -# done -# -# func_quote_for_eval ${1+"$@"} -# my_silent_option_result=$func_quote_for_eval_result -# } -# func_add_hook func_parse_options my_silent_option -# -# -# my_option_validation () -# { -# $debug_cmd -# -# $opt_silent && $opt_verbose && func_fatal_help "\ -# '--silent' and '--verbose' options are mutually exclusive." -# -# func_quote_for_eval ${1+"$@"} -# my_option_validation_result=$func_quote_for_eval_result -# } -# func_add_hook func_validate_options my_option_validation -# -# You'll alse need to manually amend $usage_message to reflect the extra -# options you parse. It's preferable to append if you can, so that -# multiple option parsing hooks can be added safely. - - -# func_options [ARG]... -# --------------------- -# All the functions called inside func_options are hookable. See the -# individual implementations for details. -func_hookable func_options -func_options () -{ - $debug_cmd - - func_options_prep ${1+"$@"} - eval func_parse_options \ - ${func_options_prep_result+"$func_options_prep_result"} - eval func_validate_options \ - ${func_parse_options_result+"$func_parse_options_result"} - - eval func_run_hooks func_options \ - ${func_validate_options_result+"$func_validate_options_result"} - - # save modified positional parameters for caller - func_options_result=$func_run_hooks_result -} - - -# func_options_prep [ARG]... -# -------------------------- -# All initialisations required before starting the option parse loop. -# Note that when calling hook functions, we pass through the list of -# positional parameters. If a hook function modifies that list, and -# needs to propogate that back to rest of this script, then the complete -# modified list must be put in 'func_run_hooks_result' before -# returning. -func_hookable func_options_prep -func_options_prep () -{ - $debug_cmd - - # Option defaults: - opt_verbose=false - opt_warning_types= - - func_run_hooks func_options_prep ${1+"$@"} - - # save modified positional parameters for caller - func_options_prep_result=$func_run_hooks_result -} - - -# func_parse_options [ARG]... -# --------------------------- -# The main option parsing loop. -func_hookable func_parse_options -func_parse_options () -{ - $debug_cmd - - func_parse_options_result= - - # this just eases exit handling - while test $# -gt 0; do - # Defer to hook functions for initial option parsing, so they - # get priority in the event of reusing an option name. - func_run_hooks func_parse_options ${1+"$@"} - - # Adjust func_parse_options positional parameters to match - eval set dummy "$func_run_hooks_result"; shift - - # Break out of the loop if we already parsed every option. - test $# -gt 0 || break - - _G_opt=$1 - shift - case $_G_opt in - --debug|-x) debug_cmd='set -x' - func_echo "enabling shell trace mode" - $debug_cmd - ;; - - --no-warnings|--no-warning|--no-warn) - set dummy --warnings none ${1+"$@"} - shift - ;; - - --warnings|--warning|-W) - test $# = 0 && func_missing_arg $_G_opt && break - case " $warning_categories $1" in - *" $1 "*) - # trailing space prevents matching last $1 above - func_append_uniq opt_warning_types " $1" - ;; - *all) - opt_warning_types=$warning_categories - ;; - *none) - opt_warning_types=none - warning_func=: - ;; - *error) - opt_warning_types=$warning_categories - warning_func=func_fatal_error - ;; - *) - func_fatal_error \ - "unsupported warning category: '$1'" - ;; - esac - shift - ;; - - --verbose|-v) opt_verbose=: ;; - --version) func_version ;; - -\?|-h) func_usage ;; - --help) func_help ;; - - # Separate optargs to long options (plugins may need this): - --*=*) func_split_equals "$_G_opt" - set dummy "$func_split_equals_lhs" \ - "$func_split_equals_rhs" ${1+"$@"} - shift - ;; - - # Separate optargs to short options: - -W*) - func_split_short_opt "$_G_opt" - set dummy "$func_split_short_opt_name" \ - "$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - # Separate non-argument short options: - -\?*|-h*|-v*|-x*) - func_split_short_opt "$_G_opt" - set dummy "$func_split_short_opt_name" \ - "-$func_split_short_opt_arg" ${1+"$@"} - shift - ;; - - --) break ;; - -*) func_fatal_help "unrecognised option: '$_G_opt'" ;; - *) set dummy "$_G_opt" ${1+"$@"}; shift; break ;; - esac - done - - # save modified positional parameters for caller - func_quote_for_eval ${1+"$@"} - func_parse_options_result=$func_quote_for_eval_result -} - - -# func_validate_options [ARG]... -# ------------------------------ -# Perform any sanity checks on option settings and/or unconsumed -# arguments. -func_hookable func_validate_options -func_validate_options () -{ - $debug_cmd - - # Display all warnings if -W was not given. - test -n "$opt_warning_types" || opt_warning_types=" $warning_categories" - - func_run_hooks func_validate_options ${1+"$@"} - - # Bail if the options were screwed! - $exit_cmd $EXIT_FAILURE - - # save modified positional parameters for caller - func_validate_options_result=$func_run_hooks_result -} - - - -## ----------------- ## -## Helper functions. ## -## ----------------- ## - -# This section contains the helper functions used by the rest of the -# hookable option parser framework in ascii-betical order. - - -# func_fatal_help ARG... -# ---------------------- -# Echo program name prefixed message to standard error, followed by -# a help hint, and exit. -func_fatal_help () -{ - $debug_cmd - - eval \$ECHO \""Usage: $usage"\" - eval \$ECHO \""$fatal_help"\" - func_error ${1+"$@"} - exit $EXIT_FAILURE -} - - -# func_help -# --------- -# Echo long help message to standard output and exit. -func_help () -{ - $debug_cmd - - func_usage_message - $ECHO "$long_help_message" - exit 0 -} - - -# func_missing_arg ARGNAME -# ------------------------ -# Echo program name prefixed message to standard error and set global -# exit_cmd. -func_missing_arg () -{ - $debug_cmd - - func_error "Missing argument for '$1'." - exit_cmd=exit -} - - -# func_split_equals STRING -# ------------------------ -# Set func_split_equals_lhs and func_split_equals_rhs shell variables after -# splitting STRING at the '=' sign. -test -z "$_G_HAVE_XSI_OPS" \ - && (eval 'x=a/b/c; - test 5aa/bb/cc = "${#x}${x%%/*}${x%/*}${x#*/}${x##*/}"') 2>/dev/null \ - && _G_HAVE_XSI_OPS=yes - -if test yes = "$_G_HAVE_XSI_OPS" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_split_equals () - { - $debug_cmd - - func_split_equals_lhs=${1%%=*} - func_split_equals_rhs=${1#*=} - test "x$func_split_equals_lhs" = "x$1" \ - && func_split_equals_rhs= - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_split_equals () - { - $debug_cmd - - func_split_equals_lhs=`expr "x$1" : 'x\([^=]*\)'` - func_split_equals_rhs= - test "x$func_split_equals_lhs" = "x$1" \ - || func_split_equals_rhs=`expr "x$1" : 'x[^=]*=\(.*\)$'` - } -fi #func_split_equals - - -# func_split_short_opt SHORTOPT -# ----------------------------- -# Set func_split_short_opt_name and func_split_short_opt_arg shell -# variables after splitting SHORTOPT after the 2nd character. -if test yes = "$_G_HAVE_XSI_OPS" -then - # This is an XSI compatible shell, allowing a faster implementation... - eval 'func_split_short_opt () - { - $debug_cmd - - func_split_short_opt_arg=${1#??} - func_split_short_opt_name=${1%"$func_split_short_opt_arg"} - }' -else - # ...otherwise fall back to using expr, which is often a shell builtin. - func_split_short_opt () - { - $debug_cmd - - func_split_short_opt_name=`expr "x$1" : 'x-\(.\)'` - func_split_short_opt_arg=`expr "x$1" : 'x-.\(.*\)$'` - } -fi #func_split_short_opt - - -# func_usage -# ---------- -# Echo short help message to standard output and exit. -func_usage () -{ - $debug_cmd - - func_usage_message - $ECHO "Run '$progname --help |${PAGER-more}' for full usage" - exit 0 -} - - -# func_usage_message -# ------------------ -# Echo short help message to standard output. -func_usage_message () -{ - $debug_cmd - - eval \$ECHO \""Usage: $usage"\" - echo - $SED -n 's|^# || - /^Written by/{ - x;p;x - } - h - /^Written by/q' < "$progpath" - echo - eval \$ECHO \""$usage_message"\" -} - - -# func_version -# ------------ -# Echo version message to standard output and exit. -func_version () -{ - $debug_cmd - - printf '%s\n' "$progname $scriptversion" - $SED -n ' - /(C)/!b go - :more - /\./!{ - N - s|\n# | | - b more - } - :go - /^# Written by /,/# warranty; / { - s|^# || - s|^# *$|| - s|\((C)\)[ 0-9,-]*[ ,-]\([1-9][0-9]* \)|\1 \2| - p - } - /^# Written by / { - s|^# || - p - } - /^warranty; /q' < "$progpath" - - exit $? -} - - -# Local variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'before-save-hook 'time-stamp) -# time-stamp-pattern: "10/scriptversion=%:y-%02m-%02d.%02H; # UTC" -# time-stamp-time-zone: "UTC" -# End: diff --git a/build-aux/gl/lib/clean-temp.c.diff b/build-aux/gl/lib/clean-temp.c.diff deleted file mode 100644 index 2eafde69..00000000 --- a/build-aux/gl/lib/clean-temp.c.diff +++ /dev/null @@ -1,14 +0,0 @@ -diff --git i/lib/clean-temp.c w/lib/clean-temp.c -index 40ec02f..1053312 100644 ---- i/lib/clean-temp.c -+++ w/lib/clean-temp.c -@@ -582,6 +582,9 @@ static bool - supports_delete_on_close () - { - static int known; /* 1 = yes, -1 = no, 0 = unknown */ -+ /* M4 wants to close and later reopen a temporary file, so -+ delete-on-close must not be used. */ -+ known = -1; - if (!known) - { - OSVERSIONINFO v; diff --git a/build-aux/gnulib b/build-aux/gnulib deleted file mode 160000 index 31bc4996..00000000 --- a/build-aux/gnulib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 31bc499696c19bb64741e56c8cd13e1a2ead87c2 diff --git a/build-aux/m4/debug.m4 b/build-aux/m4/debug.m4 deleted file mode 100644 index ec45e2de..00000000 --- a/build-aux/m4/debug.m4 +++ /dev/null @@ -1,94 +0,0 @@ -## -*- Autoconf -*- -## debug.m4 -- massage compiler flags for debugging/optimisation -## -## Copyright (C) 2000-2001, 2003, 2005-2007, 2010, 2013-2014, 2017 Free -## Software Foundation, Inc. -## Copyright (C) 1999-2000 Ralf S. Engelschall -## Written by -## Modified for M4 by Gary V. Vaughan -## -## 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 . - -# serial 9 - -# M4_CHECK_DEBUGGING -# ------------------ -# Debugging Support -AC_DEFUN([M4_CHECK_DEBUGGING], -[AC_REQUIRE([AC_PROG_CC]) -AC_ARG_ENABLE([debug], [AS_HELP_STRING([--enable-debug], - [build for debugging [default=no]])]) -AC_MSG_CHECKING([for compilation debug mode]) -AC_MSG_RESULT([${enable_debug-no}]) - -: ${rm=rm -f} -: ${RM=rm -f} - -set dummy $CC -compiler="${compiler-[$]2}" -test -n "$rm" || rm="rm -f" - -if test "X$enable_debug" = Xyes; then - AC_DISABLE_SHARED - AC_DEFINE([DEBUG], [1], - [Define this to enable additional runtime debugging]) - M4_default_preload="m4 traditional gnu load \ -import modtest mpeval shadow stdlib time" - if test "$GCC" = yes; then - case "$CFLAGS" in - *-O* ) CFLAGS=`echo $CFLAGS | $SED 's/-O[[^ ]]* / /;s/-O[[^ ]]*$//'` ;; - esac - case "$CFLAGS" in - *-g* ) ;; - * ) AC_LIBTOOL_COMPILER_OPTION([if $compiler accepts -ggdb3], - [M4_cv_prog_compiler_ggdb3], - [-ggdb3 -c conftest.$ac_ext], [], - [CFLAGS="$CFLAGS -ggdb3"], - [CFLAGS="$CFLAGS -g"]) - ;; - esac - CFLAGS="$CFLAGS -Wall" - WMORE="-Wshadow -Wpointer-arith -Wcast-align -Wnested-externs" - WMORE="$WMORE -Wmissing-prototypes -Wmissing-declarations -Winline" - AC_LIBTOOL_COMPILER_OPTION([if $compiler accepts $WMORE], - [M4_cv_prog_compiler_warning_flags], - [$WMORE -c conftest.$ac_ext], [], - [CFLAGS="$CFLAGS $WMORE"]) - - AC_LIBTOOL_COMPILER_OPTION([if $compiler accepts -Wno-long-long], - [M4_cv_prog_compiler_wnolonglong], - [-Wno-long-long -c conftest.$ac_ext], [], - [CFLAGS="$CFLAGS -Wno-long-long"]) - else - case "$CFLAGS" in - *-g* ) ;; - * ) CFLAGS="$CFLAGS -g" ;; - esac - fi -else - AC_ENABLE_SHARED - case "$CFLAGS" in - *-g* ) CFLAGS=`echo "$CFLAGS" |\ - $SED -e 's/ -g / /g;s/ -g$//;s/^-g //g;s/^-g$//'` - ;; - esac - case "$CXXFLAGS" in - *-g* ) CXXFLAGS=`echo "$CXXFLAGS" |\ - $SED -e 's/ -g / /g;s/ -g$//;s/^-g //g;s/^-g$//'` - ;; - esac -fi -])# M4_CHECK_DEBUGGING diff --git a/build-aux/m4/gmp.m4 b/build-aux/m4/gmp.m4 deleted file mode 100644 index 0e60bdcc..00000000 --- a/build-aux/m4/gmp.m4 +++ /dev/null @@ -1,77 +0,0 @@ -## -*- Autoconf -*- -## Copyright (C) 2000-2001, 2003, 2006-2008, 2010, 2013-2014, 2017 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 . - -# serial 10 - -m4_define([_M4_LIB_GMP], -[AC_ARG_WITH([gmp], - [AS_HELP_STRING([--without-gmp], - [don't use GNU multiple precision arithmetic library])], -[use_gmp=$withval], [use_gmp=yes]) - -case $use_gmp:$LIBADD_GMP:$ac_cv_header_gmp_h in - no:*) - M4_cv_using_lib_gmp=no - ;; - *::yes) - AC_MSG_WARN([gmp library not found or does not appear to work - but `gmp.h' is present]) - M4_cv_using_lib_gmp=no - ;; - *:-lgmp:no) - AC_MSG_WARN([gmp works but `gmp.h' is missing]) - M4_cv_using_lib_gmp=no - ;; - yes:*:yes) - M4_cv_using_lib_gmp=yes - ;; - *) - M4_cv_using_lib_gmp=no - AC_MSG_WARN([could not detect gmp library]) - ;; -esac -])# _M4_LIB_GMP - - -AC_DEFUN([M4_LIB_GMP], -[AC_PREREQ([2.56])dnl We use the new compiler based header checking in 2.56 -AC_CHECK_HEADERS([gmp.h], [], [], [AC_INCLUDES_DEFAULT]) -m4_pattern_allow([^M4_gmp_save_LIBS$]) -# Some versions of gmp provide mpq_init as a macro, so we need to -# include the header file, otherwise the detection will fail. -M4_gmp_save_LIBS="$LIBS" -LIBS="$LIBS -lgmp" -AC_LINK_IFELSE([AC_LANG_PROGRAM([[#if HAVE_GMP_H -# include -#endif]], - [[mpq_t n; mpq_init (n);]])], - [LIBADD_GMP=-lgmp]) -LIBS=$M4_gmp_save_LIBS -AC_SUBST([LIBADD_GMP]) - -_M4_LIB_GMP - -# Don't try to link in libgmp if we are not using it after the last call -if test "$M4_cv_using_lib_gmp" = yes; then - AC_DEFINE([USE_GMP], [1], - [Define to 1 if using the GNU multiple precision library.]) -fi - -AC_SUBST([USE_GMP], [$M4_cv_using_lib_gmp]) -])# M4_LIB_GMP diff --git a/build-aux/m4/gnulib-cache.m4 b/build-aux/m4/gnulib-cache.m4 deleted file mode 100644 index 667d2ff9..00000000 --- a/build-aux/m4/gnulib-cache.m4 +++ /dev/null @@ -1,120 +0,0 @@ -# Copyright (C) 2002-2017 Free Software Foundation, Inc. -# -# This file is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This file 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 file. If not, see . -# -# As a special exception to the GNU General Public License, -# this file may be distributed as part of a program that -# contains a configuration script generated by Autoconf, under -# the same distribution terms as the rest of that program. -# -# Generated by gnulib-tool. -# -# This file represents the specification of how gnulib-tool is used. -# It acts as a cache: It is written and read by gnulib-tool. -# In projects that use version control, this file is meant to be put under -# version control, like the configure.ac and various Makefile.am files. - - -# Specification in the form of a command-line invocation: -# gnulib-tool --import --local-dir=build-aux/gl --lib=libgnu --source-base=m4/gnu --m4-base=build-aux/m4 --doc-base=doc --tests-base=tests/gnu --aux-dir=build-aux --with-tests --with-c++-tests --no-conditional-dependencies --libtool --macro-prefix=M4 assert autobuild avltree-oset binary-io bitrotate clean-temp cloexec close-stream closein config-h configmake dirname error execute fclose fdl-1.3 fflush filenamecat flexmember fopen fopen-safer freadptr freadseek fseeko gendocs gettext git-version-gen gitlog-to-changelog gnumakefile gnupload gpl-3.0 intprops inttypes maintainer-makefile manywarnings memchr2 memcmp2 memmem mkstemp obstack obstack-printf-posix progname propername quote regex regexprops-generic rename setenv sigpipe snprintf-posix spawn-pipe sprintf-posix stdbool stdlib-safer strnlen strtod tempname unlocked-io unsetenv update-copyright vasnprintf-posix verify verror wait-process xalloc xalloc-die xmemdup0 xoset xprintf-posix xstrndup xvasprintf-posix - -# Specification in the form of a few gnulib-tool.m4 macro invocations: -gl_LOCAL_DIR([build-aux/gl]) -gl_MODULES([ - assert - autobuild - avltree-oset - binary-io - bitrotate - clean-temp - cloexec - close-stream - closein - config-h - configmake - dirname - error - execute - fclose - fdl-1.3 - fflush - filenamecat - flexmember - fopen - fopen-safer - freadptr - freadseek - fseeko - gendocs - gettext - git-version-gen - gitlog-to-changelog - gnumakefile - gnupload - gpl-3.0 - intprops - inttypes - maintainer-makefile - manywarnings - memchr2 - memcmp2 - memmem - mkstemp - obstack - obstack-printf-posix - progname - propername - quote - regex - regexprops-generic - rename - setenv - sigpipe - snprintf-posix - spawn-pipe - sprintf-posix - stdbool - stdlib-safer - strnlen - strtod - tempname - unlocked-io - unsetenv - update-copyright - vasnprintf-posix - verify - verror - wait-process - xalloc - xalloc-die - xmemdup0 - xoset - xprintf-posix - xstrndup - xvasprintf-posix -]) -gl_WITH_CXX_TESTS -gl_AVOID([]) -gl_SOURCE_BASE([m4/gnu]) -gl_M4_BASE([build-aux/m4]) -gl_PO_BASE([]) -gl_DOC_BASE([doc]) -gl_TESTS_BASE([tests/gnu]) -gl_WITH_TESTS -gl_LIB([libgnu]) -gl_MAKEFILE_NAME([]) -gl_LIBTOOL -gl_MACRO_PREFIX([M4]) -gl_PO_DOMAIN([]) -gl_WITNESS_C_MACRO([]) diff --git a/build-aux/m4/m4-error.m4 b/build-aux/m4/m4-error.m4 deleted file mode 100644 index ba9907c1..00000000 --- a/build-aux/m4/m4-error.m4 +++ /dev/null @@ -1,41 +0,0 @@ -# -*- Autoconf -*- -# m4-error.m4 -- Use the installed version of error.h if available. -# Written by Gary V. Vaughan -# -# Copyright (C) 2003-2004, 2006-2007, 2010, 2013-2014, 2017 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 . - -# serial 4 - -# M4_ERROR -# -------- -# Use the installed version of error.h if available. -AC_DEFUN([M4_ERROR], -[AC_BEFORE([gl_ERROR], [M4_ERROR]) - -AC_CHECK_HEADERS([error.h], - [ERROR_H=""], [ERROR_H="error.h"], [AC_INCLUDES_DEFAULT]) -AC_SUBST([ERROR_H]) - -if test $ac_cv_header_error_h = yes; then - INCLUDE_ERROR_H='#include ' -else - INCLUDE_ERROR_H='#include ' -fi -AC_SUBST([INCLUDE_ERROR_H]) -])# M4_ERROR diff --git a/build-aux/m4/m4-getopt.m4 b/build-aux/m4/m4-getopt.m4 deleted file mode 100644 index 2799e38c..00000000 --- a/build-aux/m4/m4-getopt.m4 +++ /dev/null @@ -1,35 +0,0 @@ -# -*- Autoconf -*- -# m4-getopt.m4 -- Use the installed version of getopt.h if available. -# Written by Gary V. Vaughan -# -# Copyright (C) 2005-2007, 2009-2010, 2013-2014, 2017 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 . - -# serial 3 - -# M4_GETOPT -# --------- -# Use the installed version of getopt.h if available. -AC_DEFUN([M4_GETOPT], -[ - m4_divert_text([INIT_PREPARE], [M4_replace_getopt=]) - m4_pushdef([AC_LIBOBJ], [M4_replace_getopt=:]) - AC_REQUIRE([gl_FUNC_GETOPT_GNU]) - m4_popdef([AC_LIBOBJ]) - AM_CONDITIONAL([GETOPT], [test -n "$M4_replace_getopt"]) -])# M4_GETOPT diff --git a/build-aux/m4/m4-gettext.m4 b/build-aux/m4/m4-gettext.m4 deleted file mode 100644 index 65c12995..00000000 --- a/build-aux/m4/m4-gettext.m4 +++ /dev/null @@ -1,35 +0,0 @@ -# -*- Autoconf -*- -# m4-gettext.m4 -- Use the installed version of GNU gettext if available. -# Written by Gary V. Vaughan -# -# Copyright (C) 2003-2004, 2006-2007, 2010, 2013-2014, 2017 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 . - -# serial 3 - -# M4_GNU_GETTEXT -# -------------- -# Use the installed version of GNU gettext if available. -AC_DEFUN([M4_GNU_GETTEXT], -[AC_BEFORE([AM_GNU_GETTEXT], [M4_GNU_GETTEXT]) -AC_CHECK_HEADERS([gettext.h], - [GETTEXT_H=""], [GETTEXT_H="gettext.h"], [AC_INCLUDES_DEFAULT]) -AC_SUBST([GETTEXT_H]) - -AC_CONFIG_FILES([po/Makefile.in]) -])# M4_GNU_GETTEXT diff --git a/build-aux/m4/m4-obstack.m4 b/build-aux/m4/m4-obstack.m4 deleted file mode 100644 index db31b01e..00000000 --- a/build-aux/m4/m4-obstack.m4 +++ /dev/null @@ -1,50 +0,0 @@ -# -*- Autoconf -*- -# m4-obstack.m4 -- the libc supplied version of obstacks if available. -# -# Copyright (C) 2000-2001, 2003-2004, 2006-2007, 2010, 2013-2014, 2017 -# Free Software Foundation, Inc. -# Written by Gary V. Vaughan -# -# 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 . - -# serial 10 - -# M4_OBSTACK -# ---------- -# Use the libc supplied version of obstacks if available. -AC_DEFUN([M4_OBSTACK], -[AC_PREREQ([2.56])dnl We use the compiler based header checking in 2.56 -AC_BEFORE([gl_OBSTACK], [M4_OBSTACK]) -AC_ARG_WITH([included-obstack], - [AS_HELP_STRING([--with-included-obstack], - [use the obstack implementation included here])]) - -AC_CHECK_HEADERS([obstack.h], [], [], [AC_INCLUDES_DEFAULT]) - -if test "x${with_included_obstack-no}" != xno; then - ac_cv_func_obstack=no -fi - -OBSTACK_H= -if test $ac_cv_func_obstack = yes; then - INCLUDE_OBSTACK_H='#include ' -else - INCLUDE_OBSTACK_H='#include ' - OBSTACK_H=obstack.h -fi -AC_SUBST([OBSTACK_H]) -AC_SUBST([INCLUDE_OBSTACK_H]) -])# M4_FUNC_OBSTACK diff --git a/build-aux/m4/m4-regex.m4 b/build-aux/m4/m4-regex.m4 deleted file mode 100644 index c1e8acdd..00000000 --- a/build-aux/m4/m4-regex.m4 +++ /dev/null @@ -1,39 +0,0 @@ -# -*- Autoconf -*- -# m4-regex.m4 -- Use the installed regex if it is good enough. -# Written by Gary V. Vaughan -# -# Copyright (C) 2003-2004, 2006-2007, 2010, 2013-2014, 2017 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 . - -# serial 4 - -# M4_REGEX([path/to/regex.c]) -# --------------------------- -# Use the installed regex if it is good enough. -AC_DEFUN([M4_REGEX], -[AC_BEFORE([gl_REGEX], [M4_REGEX]) -if test $ac_use_included_regex = no; then - INCLUDE_REGEX_H='#include ' - REGEX_H= -else - INCLUDE_REGEX_H='#include ' - REGEX_H=regex.h -fi -AC_SUBST([REGEX_H]) -AC_SUBST([INCLUDE_REGEX_H]) -])# M4_REGEX diff --git a/build-aux/m4/m4-rename.m4 b/build-aux/m4/m4-rename.m4 deleted file mode 100644 index faafd1ba..00000000 --- a/build-aux/m4/m4-rename.m4 +++ /dev/null @@ -1,46 +0,0 @@ -# -*- Autoconf -*- -# m4-rename.m4 -- Test the abilities of rename. -# Written by Eric Blake -# -# Copyright (C) 2008, 2010, 2013-2014, 2017 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 . - -# serial 1 - -# M4_RENAME -# --------- -# Detect platforms like mingw where rename can't move open files. -AC_DEFUN([M4_RENAME], -[AC_CACHE_CHECK([whether an open file can be renamed], - [M4_cv_func_rename_open_file_works], - [AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT], - [FILE *f = fopen ("conftest.1", "w+"); - int result = rename ("conftest.1", "conftest.2"); - fclose (f); remove ("conftest.1"); remove ("conftest.2"); - return result;])], - [M4_cv_func_rename_open_file_works=yes], - [M4_cv_func_rename_open_file_works=no], - [M4_cv_func_rename_open_file_works='guessing no'])]) -if test "$M4_cv_func_rename_open_file_works" = yes ; then - M4_rename_open_works=1 -else - M4_rename_open_works=0 -fi -AC_DEFINE_UNQUOTED([RENAME_OPEN_FILE_WORKS], [$M4_rename_open_works], - [Define to 1 if a file can be renamed while open, or to 0 if not.]) -]) diff --git a/build-aux/m4/m4-syscmd.m4 b/build-aux/m4/m4-syscmd.m4 deleted file mode 100644 index 2b4beb56..00000000 --- a/build-aux/m4/m4-syscmd.m4 +++ /dev/null @@ -1,60 +0,0 @@ -# -*- Autoconf -*- -# m4-syscmd.m4 -- Allow choice of syscmd shell. -# Written by Eric Blake -# -# Copyright (C) 2009-2010, 2013-2014, 2017 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 . - -# serial 1 - -# M4_SYSCMD -# --------- -# Allow user to choose different shell than /bin/sh for e?syscmd. -AC_DEFUN([M4_SYSCMD], -[AC_MSG_CHECKING([[which shell to use for syscmd]]) -AC_ARG_WITH([syscmd-shell], - [AS_HELP_STRING([--with-syscmd-shell], [shell used by syscmd [/bin/sh]])], - [case $withval in - yes[)] with_syscmd_shell=no;; - esac], [with_syscmd_shell=no]) -if test "$with_syscmd_shell" = no ; then - with_syscmd_shell=/bin/sh - if test "$cross_compiling" != yes ; then -dnl Give mingw a default that is more likely to be available. - AS_IF([AS_EXECUTABLE_P([/bin/sh$EXEEXT])], [], - [if (cmd /c) 2>/dev/null; then with_syscmd_shell=cmd; fi]) -dnl Too bad _AS_PATH_WALK is not public. - M4_save_IFS=$IFS; IFS=$PATH_SEPARATOR - for M4_dir in `if (command -p getconf PATH) 2>/dev/null ; then - command -p getconf PATH - else - echo "/bin$PATH_SEPARATOR$PATH" - fi` - do - IFS=$M4_save_IFS - test -z "$M4_dir" && continue - AS_EXECUTABLE_P(["$M4_dir/sh"]) \ - && { with_syscmd_shell=$M4_dir/sh; break; } - done - IFS=$M4_save_IFS - fi -fi -AC_MSG_RESULT([$with_syscmd_shell]) -AC_DEFINE_UNQUOTED([M4_SYSCMD_SHELL], ["$with_syscmd_shell"], - [Shell used by syscmd and esyscmd, must accept -c argument.]) -]) diff --git a/build-aux/m4/stackovf.m4 b/build-aux/m4/stackovf.m4 deleted file mode 100644 index 104f737a..00000000 --- a/build-aux/m4/stackovf.m4 +++ /dev/null @@ -1,91 +0,0 @@ -# -*- Autoconf -*- -# stackovf.m4 -- how do we deal with stack overflow? -# -# Copyright (C) 2000, 2003, 2006-2007, 2010, 2013-2014, 2017 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 . - -# serial 7 - -# M4_SYS_STACKOVF -# --------------- -AC_DEFUN([M4_SYS_STACKOVF], -[AC_PREREQ([2.60])dnl We use the _ONCE variants -AC_REQUIRE([AC_TYPE_SIGNAL])dnl - -AC_CHECK_HEADERS_ONCE([siginfo.h]) -AC_CHECK_FUNCS_ONCE([sigaction sigaltstack sigstack sigvec]) -AC_CHECK_MEMBERS([stack_t.ss_sp], [], [], -[[#include -#if HAVE_SIGINFO_H -# include -#endif -]]) - -# Code from Jim Avera . -# 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 -#include -#include -]], [[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 -]]) - AC_CHECK_TYPES([stack_t], [], - [AC_DEFINE([stack_t], [struct sigaltstack], - [Define to struct sigaltstack if stack_t is not in signal.h])], - [[#include -]]) - AC_CHECK_TYPES([sigcontext], [], [], [[#include -]]) - AC_CHECK_TYPES([siginfo_t], [], [], [[#include -#if HAVE_SIGINFO_H -# include -#endif -]]) - AC_CHECK_MEMBERS([struct sigaction.sa_sigaction], [], [], -[[#include -]]) - - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include -]], - [[struct sigaltstack x; x.ss_base = 0;]])], - [AC_DEFINE([ss_sp], [ss_base], - [Define to ss_base if stack_t has ss_base instead of ss_sp.])]) -fi -])# M4_SYS_STACKOVF diff --git a/build-aux/thanks-gen b/build-aux/thanks-gen deleted file mode 100755 index 92090ced..00000000 --- a/build-aux/thanks-gen +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/perl -nl -# Use Perl's multi-byte alignment code, via sprintf, while -# performing a rudimentary check for duplicate names and -# removing duplicate name,email pairs. -use Encode; - -BEGIN { my (%elide, %seen, %name) } - -chomp; -my ($name, $email) = split '\0', decode ('UTF-8', $_); - -if ($elide{"!$name"}) { -; # ignore this author -} elsif (index ($name, '!') == 0) { - $elide{$name}++; -} elsif ($seen{$name}++) { - warn "$0: NO-THANKS: duplicate name: $name\n"; -} else { - print encode ('UTF-8', sprintf ('%-36s', $name)), $email; -} diff --git a/cfg.mk b/cfg.mk deleted file mode 100644 index 3b5c6f17..00000000 --- a/cfg.mk +++ /dev/null @@ -1,63 +0,0 @@ -# Customize maint.mk. -*- makefile -*- -# Copyright (C) 2003-2011, 2013-2014, 2017 Free Software Foundation, -# Inc. - -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. - -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# We intentionally hide the submodule in a subdirectory -gnulib_dir = $(srcdir)/build-aux/gnulib - -# Used in maint.mk's web-manual rule -manual_title = GNU macro processor - -# Always use shorthand copyrights. -update-copyright-env = \ - UPDATE_COPYRIGHT_USE_INTERVALS=1 \ - UPDATE_COPYRIGHT_MAX_LINE_LENGTH=72 - -# Tests not to run as part of "make syntax-check". -# M4 intentionally uses a coding style that compiles under C++. -# sc_proper_name_utf8_requires_ICONV doesn't work with non-recursive Makefile -# sc_po_check assumes a directory layout that we don't quite provide -local-checks-to-skip = sc_cast_of_x_alloc_return_value \ - sc_proper_name_utf8_requires_ICONV \ - sc_po_check \ - sc_bindtextdomain - -# PRAGMA_SYSTEM_HEADER includes #, which does not work through a -# Makefile variable, so we exempt it. -_makefile_at_at_check_exceptions = ' && !/PRAGMA_SYSTEM_HEADER/' - -# Hash of NEWS contents, to ensure we don't add entries to wrong section. -old_NEWS_hash = 761ae30101b24be4aea2f564e9ceee75 - -# Indent only with spaces. -sc_prohibit_tab_based_indentation: - @re='^ * ' \ - msg='TAB in indentation; use only spaces' \ - $(_prohibit_regexp) - -# List all syntax-check exemptions: -exclude_file_name_regexp--sc_cast_of_argument_to_free = ^m4/m4private.h$ -exclude_file_name_regexp--sc_prohibit_always_true_header_tests = \ - ^Makefile.am$$ -exclude_file_name_regexp--sc_prohibit_strncpy = ^m4/path.c$$ -exclude_file_name_regexp--sc_prohibit_tab_based_indentation = \ - (^(GNU)?Makefile(\.am)?|\.mk|^HACKING|^ChangeLog.*)$$ -exclude_file_name_regexp--sc_require_config_h = \ - ^modules/(evalparse|format)\.c$$ -exclude_file_name_regexp--sc_require_config_h_first = \ - ^modules/(evalparse|format)\.c$$ -exclude_file_name_regexp--update_copyright = \ - ^(doc/m4\.texi|ltdl/m4/gnulib-cache.m4)$$ diff --git a/configure.ac b/configure.ac deleted file mode 100644 index c4644af5..00000000 --- a/configure.ac +++ /dev/null @@ -1,362 +0,0 @@ -# Configure template for GNU m4. -*-Autoconf-*- -# Copyright (C) 1991-1994, 2000-2002, 2004-2014, 2017 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 . - -dnl We depend on autotest's ./testsuite -C. -AC_PREREQ([2.62]) - -## ------------------------ ## -## Autoconf initialization. ## -## ------------------------ ## -m4_define([M4_VERSION], - m4_esyscmd([build-aux/git-version-gen .tarball-version])) -m4_bmatch(m4_defn([M4_VERSION]), [^[0-9]], [], - [m4_define([M4_VERSION], [1.9a])]) -AC_INIT([GNU M4], m4_defn([M4_VERSION]), [bug-m4@gnu.org]) - -AC_CONFIG_SRCDIR([src/m4.h]) -AC_CONFIG_AUX_DIR([build-aux]) -AC_CONFIG_MACRO_DIR([build-aux/m4]) -AC_CONFIG_LIBOBJ_DIR([m4/gnu]) -AC_CONFIG_TESTDIR([tests]) -AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_FILES([tests/m4], [chmod +x tests/m4]) - - -## -------------------------- ## -## M4 specific configuration. ## -## -------------------------- ## -dnl Autoconf recommends that packages use lowercase for their package-specific -dnl prefix for cache variables. But in the case of m4, that collides with -dnl the m4_ namespace provided by m4sugar, so we prefer M4_ as our -dnl package-specific prefix. -m4_pattern_forbid([^M4_[A-Z]]) - -AC_DEFUN([M4_DEFAULT_PRELOAD], []) -M4_default_preload="M4_DEFAULT_PRELOAD" - - -## ------------------------ ## -## Automake Initialization. ## -## ------------------------ ## -AM_INIT_AUTOMAKE([1.11.6 subdir-objects dist-bzip2 dist-xz -color-tests parallel-tests silent-rules] -m4_if(m4_index(m4_defn([M4_VERSION]), [-]), [-1], [gnits], [gnu])) -AM_SILENT_RULES([yes]) # make --enable-silent-rules the default. - - -## ------------------ ## -## C compiler checks. ## -## ------------------ ## -AC_PROG_CC -AC_DEFUN([gl_CXX_CHOICE_DEFAULT_NO]) -M4_EARLY - -# Maintainer note - comment this line out if you plan to rerun -# GNULIB_POSIXCHECK testing to see if M4 should be using more modules. -# Leave it uncommented for normal releases, for faster ./configure. -gl_ASSERT_NO_GNULIB_POSIXCHECK - -AC_SYS_LARGEFILE -AC_PROG_CPP -AM_PROG_CC_C_O -M4_CHECK_DEBUGGING - - -## --------------------------- ## -## C compiler characteristics. ## -## --------------------------- ## -AC_TYPE_SIZE_T -AC_CHECK_SIZEOF([long long int]) - -AS_CASE([$host], [*-*-os2*], [OS2_LDFLAGS=-Zargs-resp]) -AC_SUBST([OS2_LDFLAGS]) - - -## ----------------------- ## -## Libtool initialization. ## -## ----------------------- ## -LT_PREREQ([2.2]) -LT_INIT([shared dlopen win32-dll]) - -AC_ARG_ENABLE([gcc-warnings], - [AS_HELP_STRING([--enable-gcc-warnings], - [turn on lots of GCC warnings (for developers)])], - [case $enableval in - yes|no) ;; - *) AC_MSG_ERROR([bad value $enableval for gcc-warnings option]) ;; - esac - gl_gcc_warnings=$enableval], - [gl_gcc_warnings=no] -) - -if test "$gl_gcc_warnings" = yes; then - gl_WARN_ADD([-Werror], [WERROR_CFLAGS]) - AC_SUBST([WERROR_CFLAGS]) - - # This, $nw, is the list of warnings we disable. - nw= - nw="$nw -Waggregate-return" # K&R is anachronistic - nw="$nw -Wtraditional-conversion" # K&R is anachronistic - nw="$nw -Wundef" # K&R is anachronistic - nw="$nw -Wlong-long" # C90 is anachronistic - nw="$nw -Wsystem-headers" # Don't let system headers trigger warnings - nw="$nw -Wpadded" # Our structs are not packed - nw="$nw -Wformat-nonliteral" # Needed in builtin.c - nw="$nw -Wconversion" # Too many warnings for now - nw="$nw -Wsign-conversion" # Too many warnings for now - nw="$nw -Wcast-qual" # Too many warnings for now - nw="$nw -Wswitch-enum" # Too many warnings for now - # gcc 4.4.6 complains enum-compare is C++ only; gcc 4.7.0 implies it in -Wall - nw="$nw -Wenum-compare" - - # Gnulib uses '#pragma GCC diagnostic push' to silence some - # warnings, but older gcc doesn't support this. - AC_CACHE_CHECK([whether pragma GCC diagnostic push works], - [M4_cv_gcc_pragma_push_works], [ - save_CFLAGS=$CFLAGS - CFLAGS='-Wunknown-pragmas -Werror' - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - #pragma GCC diagnostic push - #pragma GCC diagnostic pop - ]])], - [M4_cv_gcc_pragma_push_works=yes], - [M4_cv_gcc_pragma_push_works=no]) - CFLAGS=$save_CFLAGS]) - if test $M4_cv_gcc_pragma_push_works = no; then - nw="$nw -Wmissing-prototypes" - nw="$nw -Wmissing-declarations" - nw="$nw -Wunreachable-code" - fi - - gl_MANYWARN_ALL_GCC([ws]) - gl_MANYWARN_COMPLEMENT([ws], [$ws], [$nw]) - for w in $ws; do - gl_WARN_ADD([$w]) - done - - gl_WARN_ADD([-fdiagnostics-show-option]) - gl_WARN_ADD([-funit-at-a-time]) - - AC_SUBST([WARN_CFLAGS]) - - AH_VERBATIM([FORTIFY_SOURCE], - [/* Enable compile-time and run-time bounds-checking, and some warnings, - without upsetting newer glibc. */ - #if defined __OPTIMIZE__ && __OPTIMIZE__ - # define _FORTIFY_SOURCE 2 - #endif - ]) -fi - -# Use gcc's -pipe option if available: for faster compilation. -case "$CFLAGS" in - *-pipe* ) ;; - * ) _LT_COMPILER_OPTION([if $compiler supports -pipe], - [M4_cv_prog_compiler_pipe], - [-pipe -c conftest.$ac_ext], [], - [CFLAGS="$CFLAGS -pipe"]) - ;; -esac - - -## ------------------------------- ## -## Dynamic Loader Characteristics. ## -## ------------------------------- ## - -LT_LIB_DLLOAD -LT_SYS_SYMBOL_USCORE - -LT_SYS_MODULE_EXT - -if test yes = "$sys_symbol_underscore"; then - libm4_shlibext=$libltdl_cv_shlibext - - AC_MSG_CHECKING([whether dlsym requires underscore prefixed symbols]) - AC_CACHE_VAL([libm4_cv_sys_dlsym_uscore], [dnl - libname=conftmod # stay within 8.3 filename limits! - cat >$libname.$ac_ext <<_M4_EOF -[#line $LINENO "configure" -#include "confdefs.h" -/* When -fvisibility=hidden is used, assume the code has been annotated - correspondingly for the symbols needed. */ -#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) -int fnord () __attribute__((visibility("default"))); -#endif -int fnord () { return 42; }] -_M4_EOF - - # fn_module_cmds module_cmds - # Execute tilde-delimited MODULE_CMDS with environment primed for - # ${module_cmds} or ${archive_cmds} type content. - fn_module_cmds () - {( # subshell avoids polluting parent global environment - module_cmds_save_ifs=$IFS; IFS='~' - for cmd in $1; do - IFS=$module_cmds_save_ifs - libobjs=$libname.$ac_objext; lib=$libname$libm4_shlibext - rpath=/not-exists; soname=$libname$libm4_shlibext; output_objdir=. - major=; versuffix=; verstring=; deplibs= - ECHO=echo; wl=$lt_prog_compiler_wl; allow_undefined_flag= - eval $cmd - done - IFS=$module_cmds_save_ifs - )} - - # Compile a loadable module using libtool macro expansion results. - $CC $pic_flag -c $libname.$ac_ext - fn_module_cmds "${module_cmds:-$archive_cmds}" - - # Try to fetch fnord with dlsym(). - libm4_dlunknown=0; libm4_dlnouscore=1; libm4_dluscore=2 - cat >conftest.$ac_ext <<_M4_EOF -[#line $LINENO "configure" -#include "confdefs.h" -#if HAVE_DLFCN_H -#include -#endif -#include -#ifndef RTLD_GLOBAL -# ifdef DL_GLOBAL -# define RTLD_GLOBAL DL_GLOBAL -# else -# define RTLD_GLOBAL 0 -# endif -#endif -#ifndef RTLD_NOW -# ifdef DL_NOW -# define RTLD_NOW DL_NOW -# else -# define RTLD_NOW 0 -# endif -#endif -int main () { - void *handle = dlopen ("`pwd`/$libname$libm4_shlibext", RTLD_GLOBAL|RTLD_NOW); - int status = $libm4_dlunknown; - if (handle) { - if (dlsym (handle, "fnord")) - status = $libm4_dlnouscore; - else { - if (dlsym (handle, "_fnord")) - status = $libm4_dluscore; - else - puts (dlerror ()); - } - dlclose (handle); - } else - puts (dlerror ()); - return status; -}] -_M4_EOF - if AC_TRY_EVAL(ac_link) && test -s "conftest$ac_exeext" 2>/dev/null; then - (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null - libm4_status=$? - case x$libm4_status in - x$libm4_dlnouscore) libm4_cv_sys_dlsym_uscore=no ;; - x$libm4_dluscore) libm4_cv_sys_dlsym_uscore=yes ;; - x*) libm4_cv_sys_dlsym_uscore=unknown ;; - esac - fi - rm -rf conftest* $libname* - ]) - sys_dlsym_uscore=$libm4_cv_sys_dlsym_uscore - AC_MSG_RESULT($sys_dlsym_uscore) - if test yes = "$sys_dlsym_uscore"; then - AC_DEFINE([DLSYM_USCORE], [1], - [Define if dlsym() requires a leading underscore in symbol names.]) - fi -fi - -AC_DEFINE_UNQUOTED([PATH_SEPARATOR], ['$PATH_SEPARATOR'], - [Define this to system search path delimiter]) - - -## ---------------- ## -## Gettext support. ## -## ---------------- ## -AM_GNU_GETTEXT([external]) -AM_GNU_GETTEXT_NEED([need-formatstring-macros]) -AM_GNU_GETTEXT_VERSION([0.16]) -M4_GNU_GETTEXT - - -## --------------- ## -## Gnulib support. ## -## --------------- ## -M4_INIT - -gl_VERSION_ETC - -# Gnulib doesn't always do things quite the way M4 would like... -M4_ERROR -M4_GETOPT -M4_OBSTACK -M4_REGEX -M4_RENAME - - -## ------------------------- ## -## C headers required by M4. ## -## ------------------------- ## -AC_CHECK_HEADERS_ONCE([limits.h]) - -if test $ac_cv_header_stdbool_h = yes; then - INCLUDE_STDBOOL_H='#include ' -else - INCLUDE_STDBOOL_H='#include ' -fi -AC_SUBST([INCLUDE_STDBOOL_H]) - - -## --------------------------------- ## -## Library functions required by M4. ## -## --------------------------------- ## -AC_CHECK_FUNCS_ONCE([calloc strerror]) - -AM_WITH_DMALLOC - -M4_SYS_STACKOVF - -# This is for the modules -AC_STRUCT_TM -AC_FUNC_STRFTIME -AC_CHECK_FUNCS_ONCE([getcwd gethostname mktime uname]) - - -## ------------------ ## -## Configure options. ## -## ------------------ ## - -M4_LIB_GMP -AM_CONDITIONAL([USE_GMP], [test "x$USE_GMP" = xyes]) -M4_SYSCMD - - -## -------- ## -## Outputs. ## -## -------- ## -AC_CONFIG_FILES([ -Makefile -doc/Makefile -m4/gnu/Makefile -m4/system.h:m4/system_.h -tests/atlocal -tests/gnu/Makefile -]) - -AC_OUTPUT diff --git a/doc/Makefile.am b/doc/Makefile.am deleted file mode 100644 index 59648e51..00000000 --- a/doc/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ -## Makefile.am - template for generating Makefile via Automake -## -## Copyright (C) 2000-2001, 2003-2010, 2013-2014, 2017 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 . -## -## Written by Gary V. Vaughan - -config_aux_dir = build-aux - -info_TEXINFOS = m4.texi -m4_TEXINFOS = regexprops-generic.texi fdl-1.3.texi gpl-3.0.texi -dist_man_MANS = $(srcdir)/m4.1 -EXTRA_DIST = gendocs_template -MAINTAINERCLEANFILES = gendocs_template -HELP2MAN = $(SHELL) $(top_srcdir)/$(config_aux_dir)/missing --run help2man - -# Build the man page once in the srcdir, rather than in every VPATH build -# dir, to match how automake builds info pages. This is safe for 'make -# distcheck' since it is distributed pre-built. -$(srcdir)/m4.1: $(top_srcdir)/.version $(top_srcdir)/src/main.c - @echo "Updating the \`man' page \`$@'"; \ - $(HELP2MAN) --name="macro processor" --source=FSF \ - --info-page=m4 --output=$@ $(top_srcdir)/src/m4$(EXEEXT) diff --git a/doc/STYLE b/doc/STYLE deleted file mode 100644 index 6b106446..00000000 --- a/doc/STYLE +++ /dev/null @@ -1,100 +0,0 @@ -GNU m4 STYLE - The way this code should look. -*- outline -*- - -Before all else this code follows the GNU coding standards and -indentation style described in standards.info. Additionally the -following restrictions on coding style apply: - -* SPACING - - + Avoid TABs in .h and .c files. See HACKING for details. - -* C STANDARD - - + All of this code is ANSI-C, GNU C extensions are conditional so that - the code will compile cleanly on non GLIBC/GCC systems. - -* SYMBOL NAMES - - + All non-static symbols have a prefix either `M4' or `m4'. - - + All exported symbols which are part of the library api have the - prefix `m4_'. - - + Symbols which are exported from the library (for efficiency perhaps) - but are not part of the supported library api have the prefix - `m4__', - - + Function names should be verb phrases; m4_module_get_field. - - + Functions which exist to be used as callbacks from API functions, and - hence which likely have strange looking parameters are named with the - suffix `_CB', to make it obvious why they look a little odd. - - + Macros which implement fast versions of functions share the - same name as the function they replace, and may not evaluate - parameters more than once. - - + Otherwise macros are in uppercase, prefixed `M4' if they are visible - to the user after installation, to help the user know when to be - careful about multiple evaluations of parameters. - - + Function names should contain the name of the module they belong to, - usually immediately after the namespace prefix: m4_module_load. - - + Variables should not be exported (not true, but I'm working on it), - but accessor functions used instead. Note the `get'/`set' part of - the symbol name comes before the module part: m4_get_module_macros. - - + Structures come with accessor macros named _ (in upper case), to make refactoring of nested structures much - easier: SYMBOL_FLAGS. - - + Structures are typedeffed separately, and the structure itself - generally not exported unless in the `m4__' namespace to support - fast accessor macros. - - + An opaque abstract data type (ADT) can have public and private fields: - By convention public fields will have exported accessor functions (and - maybe also fast macro versions of the same), and private fields will - not export accessors at all. However, there should be non-exported - (or at least in the `m4__' namespace) accessor functions for even the - private fields of an ADT to aid possible later refactoring. - -* ARCHITECTURE - - + There are four groups of sources in subdirectories: `gnu' contains - the files maintained outside of m4, as a portability layer when building - the souce for non-glibc2 machines; `m4' contains the functionality for - libm4 and enables the user to write modules; `modules' implements the - builtin macros for the m4 binary; `src' is a small wrapper program - which links libm4 and loads initial modules to implement the m4 engine. - - + The headers in gnu need to be managed carefully: gnulib headers - can be included by other files in the same directory using `#include - "file.h"', and from files in other directories with `#include - '. The include path to invocations of the compiler from - various Makefile.am are set to prevent the possibility of picking up - an m4/file.h when the system file.h (e.g stdbool.h) is present. This, - in turn means the replacement headers can live in gnulib/m4 without - suffering a renaming scheme at configure time. Don't break with the - `#include' convention, or the compile will go wrong in hard to debug - ways on some platforms. - - + Low coupling. Classes (and in C, by this I mean files of functions) - should not rely on a web of other classes to be useful, they should - communicate with as few other classes as possible. - - + High cohesion. The api and caller boundaries should be well defined - and adhered to; a class should do one thing only. - -======================================================================== - -Copyright (C) 2003, 2006, 2010, 2013-2014, 2017 Free Software -Foundation, Inc. - -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, Version 1.3 or -any later version published by the Free Software Foundation; with no -Invariant Sections, with no Front-Cover Texts, and with no Back-Cover -Texts. A copy of the license is included in the ``GNU Free -Documentation License'' file as part of this distribution. diff --git a/doc/examples/COPYING b/doc/examples/COPYING deleted file mode 100644 index e0170d74..00000000 --- a/doc/examples/COPYING +++ /dev/null @@ -1,8 +0,0 @@ -The files in this directory provide example uses of GNU M4. -The following copyright notice applies to each of these -description files. - -Copyright (C) 2006, 2010, 2013-2014, 2017 Free Software Foundation, Inc. -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. diff --git a/doc/examples/WWW/COPYING b/doc/examples/WWW/COPYING deleted file mode 100644 index e0170d74..00000000 --- a/doc/examples/WWW/COPYING +++ /dev/null @@ -1,8 +0,0 @@ -The files in this directory provide example uses of GNU M4. -The following copyright notice applies to each of these -description files. - -Copyright (C) 2006, 2010, 2013-2014, 2017 Free Software Foundation, Inc. -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. diff --git a/doc/examples/WWW/Makefile b/doc/examples/WWW/Makefile deleted file mode 100644 index c296ccf4..00000000 --- a/doc/examples/WWW/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -M4 = ./m4/src/m4 -M4OPTS = -Im4lib - -VPATH = .:m4lib - -HTM = _footer.htm _header.htm bugs.htm changelog.htm download.htm \ - features.htm feedback.htm index.htm lists.htm modules.htm \ - news.htm readme.htm thanks.htm thissite.htm todo.htm uses.htm \ - visions.htm whatis.htm - -M4LIB = m4lib/bugs.m4 m4lib/changelog.m4 m4lib/download.m4 \ - m4lib/features.m4 m4lib/feedback.m4 m4lib/html.m4 \ - m4lib/index.m4 m4lib/layout.m4 m4lib/lists.m4 m4lib/menu.m4 \ - m4lib/modules.m4 m4lib/news.m4 m4lib/readme.m4 \ - m4lib/setup.m4 m4lib/test.m4 m4lib/thanks.m4 \ - m4lib/thissite.m4 m4lib/tmpl.m4 m4lib/todo.m4 m4lib/uses.m4 \ - m4lib/visions.m4 m4lib/whatis.m4 - -all: ./m4 $(HTM) - -./m4: - ln -s ../.. m4 - -%.htm: %.m4 - @$(M4) $(M4OPTS) $< >new.htm && \ - if cmp new.htm $@ >/dev/null 2>&1; then \ - rm new.htm; \ - echo "$@ has not changed"; \ - else \ - echo "$@ updated"; \ - mv new.htm $@; \ - fi - -.FORCE: -$(HTM): .FORCE $(M4LIB) - -changelog.htm: m4/ChangeLog -readme.htm: m4/README -todo.htm: m4/TODO -news.htm: m4/NEWS -modules.htm: m4/modules/README - -.PHONY: man -man: - cd man; $(MAKE) diff --git a/doc/examples/WWW/_footer.htm b/doc/examples/WWW/_footer.htm deleted file mode 100644 index 6bed8f2c..00000000 --- a/doc/examples/WWW/_footer.htm +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/doc/examples/WWW/_header.htm b/doc/examples/WWW/_header.htm deleted file mode 100644 index 1aea7999..00000000 --- a/doc/examples/WWW/_header.htm +++ /dev/null @@ -1,231 +0,0 @@ - - - -GNU m4 - Development site - - - - - - - - - - - -
- -

GNU m4

- -

Discussion Forum

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

-General info -

- -
-

- -What is m4
-Features
-Uses of m4
- -

- -
- -
-

-Documentation -

- -
-

- -Manual - -

- -
- -
-

-Source files -

- -
-

- -README
-TODO
-NEWS
-ChangeLog
-Contributors
-Browse it
- -

- -
- -
-

-The Future -

- -
-

- -Modules
-Visions
- -

- -
- -
-

-Feedback -

- -
-

- -Mailing-lists
-Feedback
- -

- -
- -
-

-Development -

- -
-

- -Download
-Known bugs
- -

- -
- -
-

-Examples -

- -
-

- -This site - -

- -
- - - - - - - - -
diff --git a/doc/examples/WWW/m4lib/COPYING b/doc/examples/WWW/m4lib/COPYING deleted file mode 100644 index e0170d74..00000000 --- a/doc/examples/WWW/m4lib/COPYING +++ /dev/null @@ -1,8 +0,0 @@ -The files in this directory provide example uses of GNU M4. -The following copyright notice applies to each of these -description files. - -Copyright (C) 2006, 2010, 2013-2014, 2017 Free Software Foundation, Inc. -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. diff --git a/doc/examples/WWW/m4lib/bugs.m4 b/doc/examples/WWW/m4lib/bugs.m4 deleted file mode 100644 index 5d8e5f52..00000000 --- a/doc/examples/WWW/m4lib/bugs.m4 +++ /dev/null @@ -1,53 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([Known bugs in GNU m4 \__m4_version__]) - -\divert(1) -\h2([Known bugs in GNU m4]) - -\define([fixed], [\p([Fixed in version 1.4$1])]) - -\define([notme], [\p([A volunteer is badly needed for this, as I have no way of testing -this myself.])]) - -\ul([ - -\item([undivert], [undivert(0) might read from standard output], - -[\p([If calling \tt(undivert(0)) when diverting to a non-zero diversion -will cause m4 to read from standard output in an attempt to bring back -diversion 0, which is not possible.]) - -\fixed(n) - -]) - -\item([sigaltstack], [failure if sigaltstack or sigstack returns ENOSYS], - -[\p([If stack overflow detection is configured but the system doesn't -support sigaltstack(2) or sigstack(2), m4 fails when the system call -returns ENOSYS. It should silently revert to default behaviour.]) - -\notme -]) - -]) - -\p([See also the \link(todo.htm, TODO) file.]) - -\print_items - -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) - - -\item([], [], - -[\p([]) - -]) -\undivert diff --git a/doc/examples/WWW/m4lib/changelog.m4 b/doc/examples/WWW/m4lib/changelog.m4 deleted file mode 100644 index cdcab269..00000000 --- a/doc/examples/WWW/m4lib/changelog.m4 +++ /dev/null @@ -1,18 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([ChangeLog]) - -\divert(1) - -
\dnl
-\changesyntax([A<>])\dnl
-\changequote(,)\dnl
-\include(m4/ChangeLog)
-\changequote([,])\dnl
-\changesyntax([O<>])\dnl
-
- -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/download.m4 b/doc/examples/WWW/m4lib/download.m4 deleted file mode 100644 index d9ee4095..00000000 --- a/doc/examples/WWW/m4lib/download.m4 +++ /dev/null @@ -1,24 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([Download]) - -\divert(1) - -\p([In the download area there are usually several version -present. Please take only the latest.]) - -\p([The files are name \tt(m4-1.4\i(X).tar.gz) where X is a letter.]) - -\p([\link([ftp://ftp.seindal.dk/pub/rene/gnu/], [Download latest -development version]).]) - -\p([\link([ftp://ftp.seindal.dk/pub/rene/gnu/m4-1.4.tar.gz],[Download -latest stable version]).]) - -\p([\link([ftp://ftp.seindal.dk/pub/rene/gnu/djgpp/],[Download -DOS/Windows port of latest stable version]).]) - -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/features.m4 b/doc/examples/WWW/m4lib/features.m4 deleted file mode 100644 index 57b68c9e..00000000 --- a/doc/examples/WWW/m4lib/features.m4 +++ /dev/null @@ -1,58 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([New feaures since version 1.4]) - -\divert(1) - -\p(Please look at the \link(news.htm, NEWS) and the \link(changelog.htm, -ChangeLog) for all the gory details.) - -\dl( -\dt(\b(GNU m4 uses GNU Automake and GNU Autoconf for configuration.)) - -\dd(\p(This has been long overdue, and now hit is done thanks to Erick -Branderhorst.)) - -\dt(\b(GNU m4 uses GNU gettext for internationalisation.)) - -\dd(\p(GNU m4 now speaks several languages. Translations for -german, french, italian, japanese, dutch, polish, romenian and swedish -have been made.)) - -\dt(\b(Support for multiple precision arithmetic in eval.)) - -\dd(\p(If appropriately configured, GNU m4 can now do multiple precision -arithmetic in the built in macro 'eval'. If not configured, GNU m4 -will use the largest integer available for its calculations.)) - -\dt(\b(An input syntax table to change how input is parsed.)) - -\dd(\p(A new build in macro 'changesyntax' allows finer control over how input -characters are parsed into input tokens.  It is now possible to have -several one character quote strings or comment delimiters, to change the -format of macro calls, to use active characters like in TeX, and probably -most useful, to change what input characters are treated as letters when -looking for macro calls.) - -\p(See the \link(man/m4_7.html#SEC41, manual section) for more details.)) - -\dt(\b(Support for loadable modules.)) - -\dd(\p(GNU m4 now has support for dynamic loading of compiled modules at -runtime. A module can define any number of new built in macros, which -will be indistinguishable from the standard set of built in -macros. Modules can also override existing built in macros.) -) - -\dt(\b(Better control of sync-lines generation.)) - -\dd(\p(The new built in macro 'syncoutput' allows better control of the -generation of sync-lines. They can now be turned on or off at -will.)) - -) - -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/feedback.m4 b/doc/examples/WWW/m4lib/feedback.m4 deleted file mode 100644 index f61d63e5..00000000 --- a/doc/examples/WWW/m4lib/feedback.m4 +++ /dev/null @@ -1,20 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([Feedback]) - -\divert(1) - -\p(Bug reports should be sent to \link(mailto:bug-m4@gnu.org, -bug-m4@gnu.org).) - -\p(Generel discussion about GNU m4 should take place on -\link(mailto:m4-forum@seindal.dk, m4-forum).) - -\p(Informal comments about this site and GNU m4 can be sent to -\link(mailto:m4-feedback@seindal.dk, m4-feedback).) - - -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/html.m4 b/doc/examples/WWW/m4lib/html.m4 deleted file mode 100644 index 94ed69ed..00000000 --- a/doc/examples/WWW/m4lib/html.m4 +++ /dev/null @@ -1,122 +0,0 @@ -\define([n], [ -]) - -\define([concat], [\ifelse($#, 0, , - $#, 1, [$1], - [$1 \concat(\shift($@))])]) - -\define([toupper], [\translit([$*], [a-z], [A-Z])]) - -\define([container], -[\pushdef([_tag], \toupper([$1]))\dnl -\ifelse($#, 1, [<\_tag>], - $#, 2, [<\_tag>$2], - $#, 3, [<\_tag $2>$3], - [<\_tag $2>\concat(\shift(\shift($@)))])\dnl -\popdef([_tag])\dnl -]) - -\define([large_container], -[\pushdef([_tag], \toupper([$1]))\dnl -\ifelse($#, 1, [<\_tag>\n], - $#, 2, [<\_tag>\n[]$2\n\n], - $#, 3, [<\_tag $2>\n[]$3\n\n], - [<\_tag $2>\n\concat(\shift(\shift($@)))\n\n])\dnl -\popdef([_tag])\dnl -]) - -\define([large_simple_container], -[\pushdef([_tag], \toupper([$1]))\dnl -<\_tag>\n\concat(\shift($@))\n\n\dnl -\popdef([_tag])\dnl -]) - -\define([simple_container], -[\pushdef([_tag], \toupper([$1]))\dnl -<\_tag>\concat(\shift($@))\dnl -\popdef([_tag])\dnl -]) - -\define([simple_tag], -[\pushdef([_tag], \toupper([$1]))\dnl -\ifelse([$2], [], [<\_tag>], [<\_tag $2>])\dnl -\popdef([_tag])\dnl -]) - -\define([doctype], [\simple_tag([!DOCTYPE], $@)]) - -\define([html], [\large_simple_container([$0], $@)]) -\define([head], [\large_simple_container([$0], $@)]) -\define([title], [\simple_container([$0], $@)]) - -\define([meta], [\n]) -\define([http_equiv], [\n]) - -\define([body], [\large_container([$0], $@)]) - -\define([center], [\large_simple_container([$0], $@)]) -\define([right], [\large_simple_container([$0], $@)]) -\define([left], [\large_simple_container([$0], $@)]) -\define([div], [\large_container([$0], $@)]) - -\define([b], [\simple_container([$0], $@)]) -\define([i], [\simple_container([$0], $@)]) -\define([tt], [\simple_container([$0], $@)]) - -\define([table], [\large_container([$0], $@)]) -\define([tr], [\large_container([$0], $@)]) -\define([td], [\large_container([$0], $@)]) -\define([th], [\large_container([$0], $@)]) - -\define([link], [\shift($*)]) -\define([target], [\shift($*)]) - -\define([font], [\n\container([$0], $@)\n]) - -\define([h1], [\n\container([$0], $@)\n]) -\define([h2], [\n\container([$0], $@)\n]) -\define([h3], [\n\container([$0], $@)\n]) -\define([h4], [\n\container([$0], $@)\n]) -\define([h5], [\n\container([$0], $@)\n]) -\define([h6], [\n\container([$0], $@)\n]) - -\define([p], [\large_simple_container([$0], $@)]) - -\define([hr], [\simple_tag([$0], $@)]) - -\define([ul], [\large_container([$0], $@)]) -\define([ol], [\large_container([$0], $@)]) - -\define([li], [\simple_tag([$0], $@)]) - -\define([blockquote], [\large_simple_container([$0], $@)]) - -\define([dl], [\large_simple_container([$0], $@)]) -\define([dt], [\simple_container([$0], $@)]) -\define([dd], [\large_simple_container([$0], $@)]) - -\define([br], [\simple_tag([$0], $@)]) -\define([hline], [\simple_tag([$0], $@)]) - -\define([pre], [\simple_container([$0], $@)]) - - - -\define([set_title], [\define([_TITLE], [$*])]) -\set_title(_TITLE) - -\define([set_author], [\define([_AUTHOR], [$*])]) -\set_author() - -\define([set_generator], [\define([_GENERATOR], [$*])]) -\set_generator([GNU m4 \__m4_version__]) - -\define([set_keywords], [\define([_KEYWORDS], [$*])]) -\set_keywords() - -\define([set_body], [\define([_BODY], [$*])]) -\set_body() - -\define([meta_if_set], - [\ifelse(\defn([_$1]), [], [], \meta([$1], \defn([_$1])))]\dnl -) diff --git a/doc/examples/WWW/m4lib/index.m4 b/doc/examples/WWW/m4lib/index.m4 deleted file mode 100644 index dbccc67b..00000000 --- a/doc/examples/WWW/m4lib/index.m4 +++ /dev/null @@ -1,36 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([Development site]) - -\divert(1) -\h2([Current development version is \__m4_version__.]) - -\p([Development versions contain new features and experiments that might -or might not make it into the next official release. The current -development version contains among other things (browse the -\link([features.htm], [new features]) for more detail):]) - -\ul([ - \li Uses GNU Automake and GNU Autoconf for configuration. - - \li Uses GNU gettext for internationalisation. - - \li Support for multiple precision arithmetic in eval. - - \li An input syntax table to change how input is parsed. - - \li Support for loadable modules. - - \li Better control of sync-lines generation. - - \li Various bug-fixes. -]) - -\p([A new release is expected ready for Spring 2000.]) - -\p([GNU \tt(m4) 1.4 is from october 1994 and can be considered stable.]) - -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/layout.m4 b/doc/examples/WWW/m4lib/layout.m4 deleted file mode 100644 index e54002db..00000000 --- a/doc/examples/WWW/m4lib/layout.m4 +++ /dev/null @@ -1,65 +0,0 @@ -\divert(-1); -The semicolons are just to get GNU Emacs C mode to indent properly. - -\define([C_TEXT], [text="#000000"]); -\define([C_LINK], [link="#0000EF"]); -\define([C_ALINK], [vlink="#51188E"]); -\define([C_VLINK], [alink="#FF0000"]); -\define([C_BG1], [bgcolor="#FFCC99"]); -\define([C_BG2], [bgcolor="#FF9900"]); -\define([C_BG3], [bgcolor="#CC6600"]); - -\define([DO_HEADER], - [\head([\title([GNU m4 - \defn([_TITLE])])], - [\meta_if_set([AUTHOR])], - [\meta_if_set([GENERATOR])], - [\meta_if_set([KEYWORDS])], - )]); - -\define([DO_BODY], - [\body([\C_TEXT \C_BG1 \C_LINK \C_VLINK \C_ALINK], - [\table([cellpadding=5 width="100%"], - [\tr([align=left valign=bottom], - [\td([align=center valign=middle colspan="3" width="100%" \C_BG2], - [\h1([GNU m4])], - [\h2(\defn([_TITLE]))], - )], - )], - [\tr([], - [\td([align=left valign=top width="15%" \C_BG2], - [\include([menu.m4])], - )], - [\td([align=left valign=top width="90%"], - [$*], - )], - )], - )], - )] - ); - -\define([DO_LAYOUT], - [\doctype([html public "-//w3c//dtd html 4.0 transitional//en"]) -\html([\DO_HEADER], [\DO_BODY([$*])])] - ); - -\define([<], [<]); -\define([>], [>]); - -\define([showlink], [\link($1, $1)]); -\define([mailto], [\link(mailto:$1, $1)]); - - - - -\define([print_items], [\undivert(2)]) - -\define([item], [\li \link([[#]$1], [$2.]) -\pushdef([_div], \divnum)\dnl -\divert(2)\dnl -\hr([align=center width="50%"])\dnl -\h2([\target([$1], [$2])])\dnl -$3\dnl -\divert(\_div)\dnl -\popdef([_div])\dnl -]) diff --git a/doc/examples/WWW/m4lib/lists.m4 b/doc/examples/WWW/m4lib/lists.m4 deleted file mode 100644 index cc710eba..00000000 --- a/doc/examples/WWW/m4lib/lists.m4 +++ /dev/null @@ -1,32 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([Mailing lists]) - -\define([me], \link([mailto:rene@seindal.dk], [rene@seindal.dk])) - -\divert(1) - -\h3(There are two mailing lists for GNU m4) - -\dl( - -\dt(\b(\link(mailto:m4-forum@seindal.dk, m4-forum@seindal.dk))) - -\dd(\p(This list is intended for discussions between people interested -and/or participating in the further development of m4.)) - -\dt(\b(m4-announce@seindal.dk)) - -\dd(\p(Announcements regarding GNU m4 will posted here.) -\p(The volume will certainly be very low.)) - -) - -\p(Currently these lists are maintained manually. Send a message to \me -saying whether you want to subscribe or unsubscribe to any of these -lists.) - -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/menu.m4 b/doc/examples/WWW/m4lib/menu.m4 deleted file mode 100644 index 78c8edfd..00000000 --- a/doc/examples/WWW/m4lib/menu.m4 +++ /dev/null @@ -1,74 +0,0 @@ -\pushdef([header], [\tr([\td([\C_BG3], [\p([\b([$1])])])])]) - -\pushdef([separator], [\tr([\td([height=5], [])])]) - -\pushdef([_row], [\link([$1], [$2])]) - -\pushdef([_rows], - [\ifelse($#, 0, [], - $#, 1, [], - $#, 2, [\_row([$1], [$2])], - $#, 3, [\_row([$1], [$2])], - [\_row([$1], [$2])\br\n\_rows(\shift(\shift($@)))])]) - -\pushdef([rows], [\tr([\td([\p([\font([size=-1], [\b([\_rows($@)])])])])])]) - -\table([], - [\header([General info])], - [\rows( - [whatis.htm], [What is m4], - [features.htm], [Features], - [uses.htm], [Uses of m4], - )], - [\separator], - - [\header([Documentation])], - [\rows( - [man/m4_toc.html], [Manual], - )], - [\separator], - - [\header([Source files])], - [\rows( - [readme.htm], [README], - [todo.htm], [TODO], - [news.htm], [NEWS], - [changelog.htm], [ChangeLog], - [thanks.htm], [Contributors], - [m4/], [Browse it], - )], - [\separator], - - [\header([The Future])], - [\rows( - [modules.htm], [Modules], - [visions.htm], [Visions], - )], - [\separator], - - [\header([Feedback])], - [\rows( - [lists.htm], [Mailing-lists], - [feedback.htm], [Feedback], - [/forum/list.php3?num=2], [Discussion Forum], - )], - [\separator], - - [\header([Development])], - [\rows( - [download.htm], [Download], - [bugs.htm], [Known bugs], - )], - [\separator], - - [\header([Examples])], - [\rows( - [thissite.htm], [This site], - )], -) - -\popdef([header]) -\popdef([rows]) -\popdef([_rows]) -\popdef([_row]) -\popdef([separator]) diff --git a/doc/examples/WWW/m4lib/modules.m4 b/doc/examples/WWW/m4lib/modules.m4 deleted file mode 100644 index b9c148f1..00000000 --- a/doc/examples/WWW/m4lib/modules.m4 +++ /dev/null @@ -1,18 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([Modules]) - -\divert(1) - -
\dnl
-\changesyntax([A<>])\dnl
-\changequote(,)\dnl
-\include(m4/modules/README)
-\changequote([,])\dnl
-\changesyntax([O<>])\dnl
-
- -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/news.m4 b/doc/examples/WWW/m4lib/news.m4 deleted file mode 100644 index e5da0d89..00000000 --- a/doc/examples/WWW/m4lib/news.m4 +++ /dev/null @@ -1,18 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([NEWS - History of user-visible changes]) - -\divert(1) - -
\dnl
-\changesyntax([A<>])\dnl
-\changequote(,)\dnl
-\include(m4/NEWS)
-\changequote([,])\dnl
-\changesyntax([O<>])\dnl
-
- -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/readme.m4 b/doc/examples/WWW/m4lib/readme.m4 deleted file mode 100644 index 1612c7d1..00000000 --- a/doc/examples/WWW/m4lib/readme.m4 +++ /dev/null @@ -1,18 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([README]) - -\divert(1) - -
\dnl
-\changesyntax([A<>])\dnl
-\changequote(,)\dnl
-\include(m4/README)
-\changequote([,])\dnl
-\changesyntax([O<>])\dnl
-
- -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/setup.m4 b/doc/examples/WWW/m4lib/setup.m4 deleted file mode 100644 index 310b65f8..00000000 --- a/doc/examples/WWW/m4lib/setup.m4 +++ /dev/null @@ -1,7 +0,0 @@ -divert(-1) -changequote([,]) -changecom([]) -changesyntax([@\]) - -\include([html.m4]) -\include([layout.m4]) diff --git a/doc/examples/WWW/m4lib/test.m4 b/doc/examples/WWW/m4lib/test.m4 deleted file mode 100644 index 110cf12b..00000000 --- a/doc/examples/WWW/m4lib/test.m4 +++ /dev/null @@ -1,29 +0,0 @@ -include(`setup.m4') - -\divert(1) - -\define([_ideas], []) - -\define([register_idea], -[\define([H_$1], [$2])\dnl -\define([T_$1], [$3])\dnl -\define([_ideas], [\print_idea([$1])]\defn([_ideas]))]) - -\define([print_idea], [ -\target([$1], [\h2([\indir([H_$1])])]) -\indir([T_$1]) -]) - -\define([print_ideas], [\indir([_ideas])]) - -\define([idea], [\li \p([\link([[#]$1], [$2.])])\register_idea([$1], [$2], [$3])]) - -\idea([guile], [Guile as an extension language], [gfhjdsfsarhgew]) -\idea([pquote], [Persistent quotes],[asdffhfdghgdsfh]) -\idea([deps], [Dependencies generation],[afsdffasdf]) - -\print_ideas - -\undivert(1) - -\defn([_ideas]) diff --git a/doc/examples/WWW/m4lib/thanks.m4 b/doc/examples/WWW/m4lib/thanks.m4 deleted file mode 100644 index 61928d07..00000000 --- a/doc/examples/WWW/m4lib/thanks.m4 +++ /dev/null @@ -1,18 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([People who have contributed to m4]) - -\divert(1) - -
\dnl
-\changesyntax([A<>])\dnl
-\changequote(,)\dnl
-\include(m4/THANKS)
-\changequote([,])\dnl
-\changesyntax([O<>])\dnl
-
- -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/thissite.m4 b/doc/examples/WWW/m4lib/thissite.m4 deleted file mode 100644 index eecfa9cf..00000000 --- a/doc/examples/WWW/m4lib/thissite.m4 +++ /dev/null @@ -1,42 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([This site]) - -\divert(1) - -\p([This GNU m4 site is maintained by René Seindal, -(\mailto(rene@seindal.dk)).]) - -\p([All files are generated using GNU m4 \__m4_version__. You can view -the \link(m4lib/, source files). They are very simple. They use some -features from GNU m4 1.4l]) - -\p([The basic M4 definitions of quotes, comments, escapes are in -\showlink(m4lib/setup.m4). This is first included by all files to -configure the enviroment correctly for the other files. To avoid have -macros called by accident, an escape character is defined with -changesyntax. \i(This is a new feature in m4 1.4l).]) - -\p([Some fairly general macros to generate various HTML construct are -found in \showlink(m4lib/html.m4). There are macros for simple tags, -containers with and without attributes, links and a few utility macros.]) - -\p([The visual aspects of the pages are in \showlink(m4lib/layout.m4). -The macros herein generate the complete HTML structure for the pages. -There are macros for making the header and the body of the document.]) - -\p([The definition of the left hand menu is in \showlink(m4lib/menu.m4). -I convinced GNU Emacs to do the indentation by switching to c-mode.]) - -\p([The page body is passed to the layout definitions as an argument. As -the text can be large, it is first diverted and the text passed to the -layout macros is simply a call to undivert. That way a very large text -can be passed around with very little cost. This page is made with -\link(m4lib/thissite.m4, these definitions).]) - -\p([There is a single file for each HTML file.]) - -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/tmpl.m4 b/doc/examples/WWW/m4lib/tmpl.m4 deleted file mode 100644 index 8262d293..00000000 --- a/doc/examples/WWW/m4lib/tmpl.m4 +++ /dev/null @@ -1,11 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([]) - -\divert(1) -\h2([]) - -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/todo.m4 b/doc/examples/WWW/m4lib/todo.m4 deleted file mode 100644 index 7a22c151..00000000 --- a/doc/examples/WWW/m4lib/todo.m4 +++ /dev/null @@ -1,18 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([TODO - Things still to be done]) - -\divert(1) - -
\dnl
-\changesyntax([A<>])\dnl
-\changequote(,)\dnl
-\include(m4/TODO)
-\changequote([,])\dnl
-\changesyntax([O<>])\dnl
-
- -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/uses.m4 b/doc/examples/WWW/m4lib/uses.m4 deleted file mode 100644 index e29acb7a..00000000 --- a/doc/examples/WWW/m4lib/uses.m4 +++ /dev/null @@ -1,43 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([Current uses of m4]) - -\divert(1) - -\p(The MTA sendmail uses \tt(m4) for generating configuration files.) - -\p(\link(http://www.gnu.org/software/autoconf/autoconf.html, GNU -Autoconf) uses \tt(m4) to generate "configure" scripts, that are used -for configuring \link(http://www.gnu.org/, GNU) software for a -particular platform.) - -\p(Htm4l is a set of macros for generating HTML. Html4 is written by -Terry Jones (terry@cliffs.ucsd.edu). See -\showlink(http://cliffs.ucsd.edu/terry/htm4l/htm4l/main.html) for -details. ) - -\p(Various programs uses m4 to preprocess configuration files, for -example the X11 window manager fvwm.) - -\p(There is an \link(http://www.ssc.com/lg/issue22/using_m4.html, -article in the Linux Gazette) about writing HTML with GNU m4 written by -\link(mailto:bhepple@bit.net.au, Bob Hepple) . More recent versions -are kept at \link(http://www.bit.net.au/~bhepple, Bob's home site). -The macros are used to maintain a large commercial site at -\showlink(http://www.finder.com.au).) - -\p(Other examples of GNU m4 generated HTML pages, written by -\link(mailto:max@alcyone.com, Erik Max Francis) can be found at the sites -\showlink(http://www.alcyone.com/max/), -\showlink(http://www.catcam.com/), -\showlink(http://www.crank.net/) and -\showlink(http://www.pollywannacracka.com/). -) - -\p(\link(thissite.htm, These files are created with GNU m4 \__m4_version__).) - - -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/WWW/m4lib/visions.m4 b/doc/examples/WWW/m4lib/visions.m4 deleted file mode 100644 index ba238ca9..00000000 --- a/doc/examples/WWW/m4lib/visions.m4 +++ /dev/null @@ -1,232 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([The Road Ahead]) - -\define([originator], -[\p([Idea contributed by [$1]]\ifelse($#, 2, [ (\mailto([$2]))])[.])]) - -\define([noone], [\p([There is no-one working on this now. Do you want -to volunteer?])]) - - -\define([done], [\p([Done in version 1.4$1])]) - - -\divert(1) -\h2([Ideas for future versions of GNU m4]) - -\p([Here are some ideas and suggestion for the future of GNU m4, large -and small. The order here is fairly random.]) - -\ul([ - -\item([guile], [Guile as an extension language], - -[\p([\link([http://www.red-bean.com/guile/], [Guile]) can be used as an -extension language so complicated macros can be written in Scheme while -still maintaining the m4 interface. It will require some changes to the -base code, as guile cannot be used from a module.]) - -\noone -]) - - -\item([utf8], [UTF-8 or wide characters], - -[\p([GNU m4 should be able to handle UTF-8 input or wide characters so -it can be more usable for different environments.]) - -\noone -]) - - -\item([pquote], [Syntax: persistent quotes], - -[\p([Persistent quotes is a way of getting text unharmed through m4's -processing. While normal quotes are stripped when a quoted string is -read, the persistent quotes are removed just before being output. This -will ensure that the quoted text is always output verbatim.]) - -\p([The bulk of the changes will be in the parser (in input.c function -next_token). Persistent quotes cannot be nested, they must balance -within a normally quoted string, but normal quotes need not balance -within persistent quotes (neither within persistent quotes within normal -quotes). The quotes should be removed before being shipped out (in -macro.c).]) - -\noone -]) - - - - -\item([comment2], [Syntax: removable comments], - -[\p([With the syntax table a category for discardable comments can be -defined, causing that type of comments to be discarded.]) - -\noone -]) - - - - -\item([comment1], [Option: remove comments], - -[\p([There should be an option (--discard-comments) to get m4 to discard -comments instead of passing them to the output.]) - -\done(n) -]) - - - -\item([deps], [Option: show dependencies], - -[\p([There should be an options to generate makefile dependencies for an -M4 input file.]) - -\p([It is not enough to scan the files for includes, as file names can -be generated and builtins renamed. To make it work, m4 will have to do -a complete run of the input file, discard the output and print the -dependencies instead.]) - -\p([It cannot be made to work in all cases when input file names are -generated on the fly.]) - -\noone -]) - - -\item([safer], [Option: render GNU m4 safer], - -[\p([There should be a --safer option that disables all functions, that -could compromise system security if used by root. It will have to -include various functions, such as file inclusion, sub shells, module -loading, ...]) - -\noone -]) - - - -\item([import], [Option: import environment], - -[\p([An option to defined each environment variable as a macro on -startup would be useful in many cases.]) - -\done(n) -]) - - - -\item([m4expand], [Builtin: quote expanded text], - -[\p([A builtin to quote expanded text would be useful. Now it is not -possible to quote the expansion of a macro; the macro itself has to -provide the quotes. Some builtins return quoted strings, others -don't.]) - -\p([A possible solution is a build in macro that takes one argument. It -expands this argument fully and returns the quoted expansion.]) - -\p([It will require changes to input handling and macro expansion code.]) - -\noone -]) - - - -\item([perl], [Module: embedded perl], - -[\p([Perl could be embedded in m4, giving users a powerful programming -language for writing macros. A single builtin "perleval" could do the -job. First argument could be a perl function and the rest arguments. -The return value of the function as a string would be the expansion.]) - -\p([The perl interpreter should be set up when the module is loaded and -closed down before m4 exits, using the appropriate hooks in the module -interface.]) - -\p([A perl module could potentially give users access to any facility -perl has access to, such as databases.]) - -\p([On systems with perl compiled as a shared library the size penalty -would be minimal.]) - -\p([(It might not be workable as a module, as it will need to link with non-shared libraries. Don't know how it can be fixed. (RS))]) - -\noone -]) - - - -\item([output], [Module: better output control], - -[\p([It has been suggested a couple of times that it should be possible -to divert to named files, in order to create several output files.]) - -\p([I think this a bit a misunderstanding. Diversion are inteded to be -brought back later, ie, they are temporary and recoverable. Output -text, on the other hand, once output it is lost (for m4). Therefore -better output control should be made in a different way.]) - -\p([My suggestion is a set of builtins defined by a module:]) - -\pre([setoutput(file) -appendoutput(file) -pipeoutput(command)]) - -\p([With these output can be directed better, diversion can be sent to -different files, and groups of files can be built by a single m4 run. -Calling \tt(setoutput) without arguments should resume output to -standard output.]) - -\p([(Admittedly, diversion 0 (standard output) has always been -different, as it cannot be undiverted.)]) - -\noone -]) - - - -\item([require], [Module: require/provide functionality], - -[\p([Two new builtins \tt(require) and \tt(provide) could provide a -handy interface to include. It has proven difficult to write these -robustly as normal macros. As an example, the files \tt(test.m4) and -\tt(../test.m4) could be the same file or different files depending on -the search path.]) - -\noone -]) - - -]) - - - -\p([See also the \link(todo.htm, TODO) file.]) - -\print_items - - - -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) - -\divert(3)saljdfnaskdjfndsa\divert(-1) - - - - -\item([], [], - -[\p([]) - -\noone -]) - -\undivert diff --git a/doc/examples/WWW/m4lib/whatis.m4 b/doc/examples/WWW/m4lib/whatis.m4 deleted file mode 100644 index 2fa1c426..00000000 --- a/doc/examples/WWW/m4lib/whatis.m4 +++ /dev/null @@ -1,48 +0,0 @@ -include(`setup.m4') - -\set_author([René Seindal]) -\set_title([What is GNU m4]) - -\divert(1) - -\p([GNU \tt(m4) is an implementation of the traditional Unix macro -processor. GNU m4 is mostly compatible with the System V, Release 3 -version, and SVR4, although it has some extensions (for example, -handling more than 9 positional parameters to macros). GNU \tt(m4) -also has built-in functions for including files, running shell -commands, doing arithmetic, etc.]) - -\p([GNU \tt(m4) is a macro processor, in the sense that it copies its -input to the output, expanding macros as it goes. Macros are either -builtin or user-defined, and can take any number of arguments. Besides -just doing macro expansion, m4 has builtin functions for including named -files, running UNIX commands, doing integer arithmetic, manipulating -text in various ways, recursion, etc... m4 can be used either as a -front-end to a compiler, or as a macro processor in its own right.]) - -\p([The m4 macro processor is widely available on all UNIXes. Usually, -only a small percentage of users are aware of its existence. However, -those who do often become commited users. The growing popularity of GNU -Autoconf, which prerequires GNU m4 for generating the `configure' -scripts, is an incentive for many to install it, while these people will -not themselves program in m4.]) - -\p([Some people found m4 to be fairly addictive. They first use m4 for -simple problems, then take bigger and bigger challenges, learning how to -write complex m4 sets of macros along the way. Once really addicted, -users pursue writing of sophisticated m4 applications even to solve -simple problems, devoting more time debugging their m4 scripts than -doing real work. Beware that m4 may be dangerous for the health of -compulsive programmers.]) - -\p([Autoconf needs GNU m4 for generating `configure' scripts, but not for -running them.]) - -\p([GNU m4 is a Unix program. It is designed to work in a Unix-like -environment. GNU m4 1.4 has, however, been ported to DJGPP, the GNU C -compiler for DOS/Windows. These files are present in the -\link(download.htm, download area).]) - -\divert(0)\dnl -\DO_LAYOUT([\undivert(1)]) -\divert(-1) diff --git a/doc/examples/capitalize.m4 b/doc/examples/capitalize.m4 deleted file mode 100644 index d4e4a502..00000000 --- a/doc/examples/capitalize.m4 +++ /dev/null @@ -1,12 +0,0 @@ -divert(`-1') -# upcase(text) -# downcase(text) -# capitalize(text) -# change case of text, simple version -define(`upcase', `translit(`$*', `a-z', `A-Z')') -define(`downcase', `translit(`$*', `A-Z', `a-z')') -define(`_capitalize', - `regexp(`$1', `^\(\w\)\(\w*\)', - `upcase(`\1')`'downcase(`\2')')') -define(`capitalize', `patsubst(`$1', `\w+', `_$0(`\&')')') -divert`'dnl diff --git a/doc/examples/capitalize2.m4 b/doc/examples/capitalize2.m4 deleted file mode 100644 index 154dc505..00000000 --- a/doc/examples/capitalize2.m4 +++ /dev/null @@ -1,19 +0,0 @@ -divert(`-1') -# upcase(text) -# downcase(text) -# capitalize(text) -# change case of text, improved version -define(`upcase', `translit(`$*', `a-z', `A-Z')') -define(`downcase', `translit(`$*', `A-Z', `a-z')') -define(`_arg1', `$1') -define(`_to_alt', `changequote(`<<[', `]>>')') -define(`_from_alt', `changequote(<<[`]>>, <<[']>>)') -define(`_upcase_alt', `translit(<<[$*]>>, <<[a-z]>>, <<[A-Z]>>)') -define(`_downcase_alt', `translit(<<[$*]>>, <<[A-Z]>>, <<[a-z]>>)') -define(`_capitalize_alt', - `regexp(<<[$1]>>, <<[^\(\w\)\(\w*\)]>>, - <<[_upcase_alt(<<[<<[\1]>>]>>)_downcase_alt(<<[<<[\2]>>]>>)]>>)') -define(`capitalize', - `_arg1(_to_alt()patsubst(<<[<<[$*]>>]>>, <<[\w+]>>, - _from_alt()`]>>_$0_alt(<<[\&]>>)<<['_to_alt())_from_alt())') -divert`'dnl diff --git a/doc/examples/comments.m4 b/doc/examples/comments.m4 deleted file mode 100644 index c1e3be0a..00000000 --- a/doc/examples/comments.m4 +++ /dev/null @@ -1,7 +0,0 @@ -# An ordinary comment -define(`foo', # A comment in a macro -`Macro `foo' expansion') -foo -define(`comment', `*** Macro `comment' expansion ***') -changecom(`@', `@') -foo diff --git a/doc/examples/curry.m4 b/doc/examples/curry.m4 deleted file mode 100644 index 00997c38..00000000 --- a/doc/examples/curry.m4 +++ /dev/null @@ -1,7 +0,0 @@ -divert(`-1') -# curry(macro, args) -# Expand to a macro call that takes one argument, then invoke -# macro(args, extra). -define(`curry', `$1(shift($@,)_$0') -define(`_curry', ``$1')') -divert`'dnl diff --git a/doc/examples/ddivert.m4 b/doc/examples/ddivert.m4 deleted file mode 100644 index e6e0017e..00000000 --- a/doc/examples/ddivert.m4 +++ /dev/null @@ -1,4 +0,0 @@ -divert(1)Text diverted a first time. -divert(0)undivert(1)dnl -divert(1)Text diverted a second time. -divert(0)undivert(1)dnl diff --git a/doc/examples/debug.m4 b/doc/examples/debug.m4 deleted file mode 100644 index 16f4c74e..00000000 --- a/doc/examples/debug.m4 +++ /dev/null @@ -1,4 +0,0 @@ -define(`countdown', `$1 ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Liftoff')') -debugmode(`aeqc') -traceon(`countdown') -countdown(2) diff --git a/doc/examples/esyscmd.m4 b/doc/examples/esyscmd.m4 deleted file mode 100644 index 3c856e02..00000000 --- a/doc/examples/esyscmd.m4 +++ /dev/null @@ -1,6 +0,0 @@ -# Cannot use real hostname program because test would fail -define(`hostname', esyscmd(`echo www.gnu.org'))dnl -`hostname = >>'hostname`<<' -define(`hostname', -pushdef(`_tmp', `$1')_tmp(translit(esyscmd(`echo www.gnu.org'), `.', `,'))`'popdef(`_tmp'))dnl -`hostname = >>'hostname`<<' diff --git a/doc/examples/exp.m4 b/doc/examples/exp.m4 deleted file mode 100644 index e2bcf943..00000000 --- a/doc/examples/exp.m4 +++ /dev/null @@ -1,3 +0,0 @@ -define(`countdown', `$1 -ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Done')')dnl -countdown(7) diff --git a/doc/examples/foreach.m4 b/doc/examples/foreach.m4 deleted file mode 100644 index 9be25b08..00000000 --- a/doc/examples/foreach.m4 +++ /dev/null @@ -1,8 +0,0 @@ -divert(`-1') -# foreach(x, (item_1, item_2, ..., item_n), stmt) -# parenthesized list, simple version -define(`foreach', `pushdef(`$1')_foreach($@)popdef(`$1')') -define(`_arg1', `$1') -define(`_foreach', `ifelse(`$2', `()', `', - `define(`$1', _arg1$2)$3`'$0(`$1', (shift$2), `$3')')') -divert`'dnl diff --git a/doc/examples/foreach2.m4 b/doc/examples/foreach2.m4 deleted file mode 100644 index 74d00fb6..00000000 --- a/doc/examples/foreach2.m4 +++ /dev/null @@ -1,10 +0,0 @@ -include(`quote.m4')dnl -divert(`-1') -# foreach(x, (item_1, item_2, ..., item_n), stmt) -# parenthesized list, improved version -define(`foreach', `pushdef(`$1')_$0(`$1', - (dquote(dquote_elt$2)), `$3')popdef(`$1')') -define(`_arg1', `$1') -define(`_foreach', `ifelse(`$2', `(`')', `', - `define(`$1', _arg1$2)$3`'$0(`$1', (dquote(shift$2)), `$3')')') -divert`'dnl diff --git a/doc/examples/foreachq.m4 b/doc/examples/foreachq.m4 deleted file mode 100644 index d34fb5b9..00000000 --- a/doc/examples/foreachq.m4 +++ /dev/null @@ -1,9 +0,0 @@ -include(`quote.m4')dnl -divert(`-1') -# foreachq(x, `item_1, item_2, ..., item_n', stmt) -# quoted list, simple version -define(`foreachq', `pushdef(`$1')_foreachq($@)popdef(`$1')') -define(`_arg1', `$1') -define(`_foreachq', `ifelse(quote($2), `', `', - `define(`$1', `_arg1($2)')$3`'$0(`$1', `shift($2)', `$3')')') -divert`'dnl diff --git a/doc/examples/foreachq2.m4 b/doc/examples/foreachq2.m4 deleted file mode 100644 index f57d3edf..00000000 --- a/doc/examples/foreachq2.m4 +++ /dev/null @@ -1,10 +0,0 @@ -include(`quote.m4')dnl -divert(`-1') -# foreachq(x, `item_1, item_2, ..., item_n', stmt) -# quoted list, improved version -define(`foreachq', `pushdef(`$1')_$0($@)popdef(`$1')') -define(`_arg1q', ``$1'') -define(`_rest', `ifelse(`$#', `1', `', `dquote(shift($@))')') -define(`_foreachq', `ifelse(`$2', `', `', - `define(`$1', _arg1q($2))$3`'$0(`$1', _rest($2), `$3')')') -divert`'dnl diff --git a/doc/examples/foreachq3.m4 b/doc/examples/foreachq3.m4 deleted file mode 100644 index 5e656727..00000000 --- a/doc/examples/foreachq3.m4 +++ /dev/null @@ -1,9 +0,0 @@ -divert(`-1') -# foreachq(x, `item_1, item_2, ..., item_n', stmt) -# quoted list, alternate improved version -define(`foreachq', `ifelse(`$2', `', `', - `pushdef(`$1')_$0(`$1', `$3', `', $2)popdef(`$1')')') -define(`_foreachq', `ifelse(`$#', `3', `', - `define(`$1', `$4')$2`'$0(`$1', `$2', - shift(shift(shift($@))))')') -divert`'dnl diff --git a/doc/examples/foreachq4.m4 b/doc/examples/foreachq4.m4 deleted file mode 100644 index 3da64c92..00000000 --- a/doc/examples/foreachq4.m4 +++ /dev/null @@ -1,13 +0,0 @@ -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/doc/examples/forloop.m4 b/doc/examples/forloop.m4 deleted file mode 100644 index fdca2608..00000000 --- a/doc/examples/forloop.m4 +++ /dev/null @@ -1,6 +0,0 @@ -divert(`-1') -# forloop(var, from, to, stmt) - simple version -define(`forloop', `pushdef(`$1', `$2')_forloop($@)popdef(`$1')') -define(`_forloop', - `$4`'ifelse($1, `$3', `', `define(`$1', incr($1))$0($@)')') -divert`'dnl diff --git a/doc/examples/forloop2.m4 b/doc/examples/forloop2.m4 deleted file mode 100644 index b7154e86..00000000 --- a/doc/examples/forloop2.m4 +++ /dev/null @@ -1,12 +0,0 @@ -divert(`-1') -# forloop(var, from, to, stmt) - improved version: -# works even if VAR is not a strict macro name -# performs sanity check that FROM is larger than TO -# allows complex numerical expressions in TO and FROM -define(`forloop', `ifelse(eval(`($2) <= ($3)'), `1', - `pushdef(`$1')_$0(`$1', eval(`$2'), - eval(`$3'), `$4')popdef(`$1')')') -define(`_forloop', - `define(`$1', `$2')$4`'ifelse(`$2', `$3', `', - `$0(`$1', incr(`$2'), `$3', `$4')')') -divert`'dnl diff --git a/doc/examples/forloop3.m4 b/doc/examples/forloop3.m4 deleted file mode 100644 index 98db20f3..00000000 --- a/doc/examples/forloop3.m4 +++ /dev/null @@ -1,13 +0,0 @@ -divert(`-1') -# forloop_arg(from, to, macro) - invoke MACRO(value) for -# each value between FROM and TO, without define overhead -define(`forloop_arg', `ifelse(eval(`($1) <= ($2)'), `1', - `_forloop(`$1', eval(`$2'), `$3(', `)')')') -# forloop(var, from, to, stmt) - refactored to share code -define(`forloop', `ifelse(eval(`($2) <= ($3)'), `1', - `pushdef(`$1')_forloop(eval(`$2'), eval(`$3'), - `define(`$1',', `)$4')popdef(`$1')')') -define(`_forloop', - `$3`$1'$4`'ifelse(`$1', `$2', `', - `$0(incr(`$1'), `$2', `$3', `$4')')') -divert`'dnl diff --git a/doc/examples/fstab.m4 b/doc/examples/fstab.m4 deleted file mode 100644 index 8d10e176..00000000 --- a/doc/examples/fstab.m4 +++ /dev/null @@ -1,6 +0,0 @@ -define(`concat', `translit(``$*'', ` ')') -define(`fsent', `format(`%-25s %-16s nfs %-16s 0 0', `$1:$2', `$3', concat$4)') - -fsent(freja, /home/gevn, /home/gevn, (rw, soft, bg, grpid)) -fsent(freja, /home/freja, /home/freja, (rw, soft, grpid)) -fsent(rimfaxe, /home/rimfaxe, /home/rimfaxe, (rw, soft, bg)) diff --git a/doc/examples/hanoi.m4 b/doc/examples/hanoi.m4 deleted file mode 100644 index 32fd8a41..00000000 --- a/doc/examples/hanoi.m4 +++ /dev/null @@ -1,17 +0,0 @@ -divert(-1) - -# move(from, to) -define(`move', `Move one disk from `$1' to `$2'. -') - -# _hanoi (cnt, from, to, aux) -define(`_hanoi', `ifelse(eval(`$1'<=1), 1, `move($2, $3)', -`$0(decr($1), $2, $4, $3)move($2, $3)$0(decr($1), $4, $3, $2)')') - -# hanoi (cnt) -define(`hanoi', `_$0(`$1', source, destination, auxilliary)') - -# traceon(`move', `_hanoi', `decr') -divert`'dnl - -hanoi(3) diff --git a/doc/examples/incl-test.m4 b/doc/examples/incl-test.m4 deleted file mode 100644 index 323fa05b..00000000 --- a/doc/examples/incl-test.m4 +++ /dev/null @@ -1,3 +0,0 @@ -dnl noauto -`include test file.' -define() diff --git a/doc/examples/incl.m4 b/doc/examples/incl.m4 deleted file mode 100644 index ab9572eb..00000000 --- a/doc/examples/incl.m4 +++ /dev/null @@ -1,3 +0,0 @@ -Include file start -foo -Include file end diff --git a/doc/examples/include.m4 b/doc/examples/include.m4 deleted file mode 100644 index 8e9d9d2f..00000000 --- a/doc/examples/include.m4 +++ /dev/null @@ -1,7 +0,0 @@ -Beginning. -include(`NOFILE') -Intermediate -include(`incl-test.m4') -After -include(`NOFILE') -very late diff --git a/doc/examples/indir.m4 b/doc/examples/indir.m4 deleted file mode 100644 index 51d2b64f..00000000 --- a/doc/examples/indir.m4 +++ /dev/null @@ -1,10 +0,0 @@ -define(`%%$$##', `>>>$0<<< cnt $#') - -# indir(`%%$$##', nonsense, nonsense) -indir(`%%$$##', nonsense, nonsense) - -# indir(`indir', `%%$$##', nonsense) -indir(`indir', `%%$$##', nonsense) - -# indir(`indir', `indir', `indir', `indir', `%%$$##') -indir(`indir', `indir', `indir', `indir', `%%$$##') diff --git a/doc/examples/join.m4 b/doc/examples/join.m4 deleted file mode 100644 index 8687ac70..00000000 --- a/doc/examples/join.m4 +++ /dev/null @@ -1,15 +0,0 @@ -divert(`-1') -# join(sep, args) - join each non-empty ARG into a single -# string, with each element separated by SEP -define(`join', -`ifelse(`$#', `2', ``$2'', - `ifelse(`$2', `', `', ``$2'_')$0(`$1', shift(shift($@)))')') -define(`_join', -`ifelse(`$#$2', `2', `', - `ifelse(`$2', `', `', ``$1$2'')$0(`$1', shift(shift($@)))')') -# joinall(sep, args) - join each ARG, including empty ones, -# into a single string, with each element separated by SEP -define(`joinall', ``$2'_$0(`$1', shift($@))') -define(`_joinall', -`ifelse(`$#', `2', `', ``$1$3'$0(`$1', shift(shift($@)))')') -divert`'dnl diff --git a/doc/examples/loop.m4 b/doc/examples/loop.m4 deleted file mode 100644 index b2fc64c4..00000000 --- a/doc/examples/loop.m4 +++ /dev/null @@ -1,18 +0,0 @@ -dnl Stress test for recursion algorithms. Usage: -dnl m4 -Ipath/to/examples [-Doptions] loop.m4 -dnl Options include: -dnl -Dalt[=] - test with foreachq instead of foreachq2, default 3 -dnl -Dlimit= - set upper limit of sequence to , default 1000 -dnl -Dverbose - print the sequence to the screen, rather than discarding -dnl -Ddebug[=] - execute after forloop but before foreach -dnl -Dsleep= - sleep for seconds before exit, to allow time -dnl to examine peak process memory usage -include(`forloop2.m4')dnl -include(`quote.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 -foreachq(`i', dquote(1forloop(`i', `2', limit, `,i'))debug, ` i') -ifdef(`sleep',`syscmd(`echo done>/dev/tty;sleep 'sleep)')dnl diff --git a/doc/examples/misc.m4 b/doc/examples/misc.m4 deleted file mode 100644 index 979b51aa..00000000 --- a/doc/examples/misc.m4 +++ /dev/null @@ -1,8 +0,0 @@ -divert(-1) -define(`USER', `root') -define(`TMP', maketemp(`/tmp/hejXXXXXX')) -syscmd(`grep "^'USER`:" /etc/passwd | awk -F: "{print \$3}"' > TMP) -define(`UID', include(TMP)) -syscmd(`rm -f' TMP) -divert -UID diff --git a/doc/examples/modtest.m4 b/doc/examples/modtest.m4 deleted file mode 100644 index 17e6b02f..00000000 --- a/doc/examples/modtest.m4 +++ /dev/null @@ -1,8 +0,0 @@ -dnl Copyright (C) 2006, 2010, 2013-2014, 2017 Free Software Foundation, -dnl Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it -dnl with or without modifications, as long as this notice is preserved. -load(`modtest') -test -Dumpdef: dumpdef(`test'). diff --git a/doc/examples/multiquotes.m4 b/doc/examples/multiquotes.m4 deleted file mode 100644 index b56cfbd8..00000000 --- a/doc/examples/multiquotes.m4 +++ /dev/null @@ -1,17 +0,0 @@ -traceon -changequote([,])dnl -changequote([``], [''])dnl -````traceon'''' -define(``foo'', ````FOO'''')dnl -dumpdef(``foo'')dnl -changequote(``!'', ``!'')dnl -!foo! -foo -dumpdef(!foo!)dnl -define(!bar!, !BAR!) -bar -changequote(!>*>*>*>*>!, !<*<*<*<**>*>*>*>foo bar<*<*<*<*< -foo bar ->*>*>*>*>*>*><*<*<*<*<*<*< -dumpdef(>*>*>*>*>foo<*<*<*<*<, >*>*>*>*>bar<*<*<*<*<)dnl diff --git a/doc/examples/patsubst.m4 b/doc/examples/patsubst.m4 deleted file mode 100644 index 9b4c7591..00000000 --- a/doc/examples/patsubst.m4 +++ /dev/null @@ -1,8 +0,0 @@ -# traceon(`patsubst') -patsubst(`GNUs not Unix.', `^', `OBS: ') -patsubst(`GNUs not Unix.', `\<', `OBS: ') -patsubst(`GNUs not Unix.', `\<\w', `\0=') -patsubst(`GNUs not Unix.', `\w*', `(\0)') -patsubst(`GNUs not Unix.', `\w+', `(\0)') -patsubst(`GNUs not Unix.', `\w+') -patsubst(`GNUs not '` Unix.', `[ ]+', ` ') diff --git a/doc/examples/pushpop.m4 b/doc/examples/pushpop.m4 deleted file mode 100644 index d0f2ebb8..00000000 --- a/doc/examples/pushpop.m4 +++ /dev/null @@ -1,25 +0,0 @@ -divert(-1) -pushdef(`hej', `def 1.') -dumpdef(`hej') -pushdef(`hej', `def 2.') -dumpdef(`hej') -pushdef(`hej', `def 3.') -dumpdef(`hej') -pushdef(`hej', `def 4.') -dumpdef(`hej') - -popdef(`hej') -dumpdef(`hej') -popdef(`hej') -dumpdef(`hej') -popdef(`hej') -dumpdef(`hej') -popdef(`hej') -dumpdef(`hej') -popdef(`hej') -dumpdef(`hej') -popdef(`hej') - -dumpdef(`mac2') -popdef(`mac2') -dumpdef(`mac2') diff --git a/doc/examples/quote.m4 b/doc/examples/quote.m4 deleted file mode 100644 index fae52c3e..00000000 --- a/doc/examples/quote.m4 +++ /dev/null @@ -1,9 +0,0 @@ -divert(`-1') -# quote(args) - convert args to single-quoted string -define(`quote', `ifelse(`$#', `0', `', ``$*'')') -# dquote(args) - convert args to quoted list of quoted strings -define(`dquote', ``$@'') -# dquote_elt(args) - convert args to list of double-quoted strings -define(`dquote_elt', `ifelse(`$#', `0', `', `$#', `1', ```$1''', - ```$1'',$0(shift($@))')') -divert`'dnl diff --git a/doc/examples/regexp.m4 b/doc/examples/regexp.m4 deleted file mode 100644 index a4ca573e..00000000 --- a/doc/examples/regexp.m4 +++ /dev/null @@ -1,12 +0,0 @@ -traceon(`regexp')dnl -regexp(`hej med dig', `.*', `>>\0<<') -regexp(`hej med dig', `\w*', `>>\0<<') -regexp(`hej med dig', `.+', `>>\0<<') -regexp(`hej med dig', `m\w+', `>>\0<<') -regexp(`hej med dig', `m\(.*\)', `>>\0<< >>\1<<') - -regexp(`hej med dig', `.*') -regexp(`hej med dig', `\w*') -regexp(`hej med dig', `.+') -regexp(`hej med dig', `m\w+') -regexp(`hej med dig', `m\(.*\)') diff --git a/doc/examples/reverse.m4 b/doc/examples/reverse.m4 deleted file mode 100644 index 7e2374e2..00000000 --- a/doc/examples/reverse.m4 +++ /dev/null @@ -1,4 +0,0 @@ -define(`reverse', `ifelse(eval($# > 1), 1, `reverse(shift($@)), `$1'', ``$1'')') -``'' => reverse. -``hej'' => reverse(hej). -``hej, med, dig'' => reverse(hej, med, dig). diff --git a/doc/examples/shadow.m4 b/doc/examples/shadow.m4 deleted file mode 100644 index d82b8443..00000000 --- a/doc/examples/shadow.m4 +++ /dev/null @@ -1,58 +0,0 @@ -dnl Copyright (C) 2006, 2010, 2013-2014, 2017 Free Software Foundation, -dnl Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it -dnl with or without modifications, as long as this notice is preserved. -# no modules loaded yet -test -shadow - -# define our own macros for `test' and `shadow' -define(`test', `local::`test'') -define(`shadow', `local::`shadow'') -test -shadow - -# module Shadow defines `shadow' and `test' macros -load(`shadow') -dumpdef(`test') -dumpdef(`shadow') -test -shadow - -# save the definition of `test' from the Shadow module -define(`Shadow::test', defn(`test')) - -# module Test also defines a `test' macro -load(`modtest') -dumpdef(`test') -dumpdef(`shadow') -test -shadow - -# Reloading Shadow shouldn't affect anything -load(`shadow') -dumpdef(`test') -dumpdef(`shadow') -test -shadow - -# Unloading Test will unshadow the test definition in Shadow -unload(`modtest') -dumpdef(`test') -dumpdef(`shadow') -test -shadow - -# Unloading Shadow once has no effect (we loaded it twice) -unload(`shadow') -dumpdef(`test') -dumpdef(`shadow') -test -shadow - -# Unloading Shadow again will revert to copying `test' and the local -# `shadow' macro. -unload(`shadow') -test -shadow diff --git a/doc/examples/stack.m4 b/doc/examples/stack.m4 deleted file mode 100644 index c1b98333..00000000 --- a/doc/examples/stack.m4 +++ /dev/null @@ -1,16 +0,0 @@ -divert(`-1') -# stack_foreach(macro, action) -# Invoke ACTION with a single argument of each definition -# from the definition stack of MACRO, starting with the oldest. -define(`stack_foreach', -`_stack_reverse(`$1', `tmp-$1')'dnl -`_stack_reverse(`tmp-$1', `$1', `$2(defn(`$1'))')') -# stack_foreach_lifo(macro, action) -# Invoke ACTION with a single argument of each definition -# from the definition stack of MACRO, starting with the newest. -define(`stack_foreach_lifo', -`_stack_reverse(`$1', `tmp-$1', `$2(defn(`$1'))')'dnl -`_stack_reverse(`tmp-$1', `$1')') -define(`_stack_reverse', -`ifdef(`$1', `pushdef(`$2', defn(`$1'))$3`'popdef(`$1')$0($@)')') -divert`'dnl diff --git a/doc/examples/stack_sep.m4 b/doc/examples/stack_sep.m4 deleted file mode 100644 index 767d15e2..00000000 --- a/doc/examples/stack_sep.m4 +++ /dev/null @@ -1,17 +0,0 @@ -divert(`-1') -# stack_foreach_sep(macro, pre, post, sep) -# Invoke PRE`'defn`'POST with a single argument of each definition -# from the definition stack of MACRO, starting with the oldest, and -# separated by SEP between definitions. -define(`stack_foreach_sep', -`_stack_reverse_sep(`$1', `tmp-$1')'dnl -`_stack_reverse_sep(`tmp-$1', `$1', `$2`'defn(`$1')$3', `$4`'')') -# stack_foreach_sep_lifo(macro, pre, post, sep) -# Like stack_foreach_sep, but starting with the newest definition. -define(`stack_foreach_sep_lifo', -`_stack_reverse_sep(`$1', `tmp-$1', `$2`'defn(`$1')$3', `$4`'')'dnl -`_stack_reverse_sep(`tmp-$1', `$1')') -define(`_stack_reverse_sep', -`ifdef(`$1', `pushdef(`$2', defn(`$1'))$3`'popdef(`$1')$0( - `$1', `$2', `$4$3')')') -divert`'dnl diff --git a/doc/examples/stdlib.m4 b/doc/examples/stdlib.m4 deleted file mode 100644 index 14df4575..00000000 --- a/doc/examples/stdlib.m4 +++ /dev/null @@ -1,45 +0,0 @@ -dnl Copyright (C) 2006, 2010, 2013-2014, 2017 Free Software Foundation, -dnl Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it -dnl with or without modifications, as long as this notice is preserved. -load(`stdlib') - -`getenv - 'getenv(PATH) - -setenv TEST=??? setenv(`TEST', `???') -getenv TEST - getenv(`TEST') - -setenv TEST=Second test setenv(`TEST', `Second test') -getenv TEST - getenv(`TEST') - -unsetenv TEST unsetenv(`TEST') -getenv TEST - getenv(`TEST') - - - -`getlogin - 'getlogin -`getcwd = 'getcwd -`getpid - 'getpid -`getppid - 'getppid - -syscmd(`ps ajx|grep m4') - -`getuid - 'getuid - -user root - getpwnam(`root') -user sync - getpwnam(`sync') -user rene - getpwnam(`rene') - -uid 5 - getpwuid(5) -me - getpwuid(getuid) - -`hostname = 'hostname - -`rand' - rand,rand,rand,rand -`srand' srand -`rand' - rand,rand,rand,rand -`srand' srand -`rand' - rand,rand,rand,rand - -`uname - ' uname diff --git a/doc/examples/sysv-args.m4 b/doc/examples/sysv-args.m4 deleted file mode 100644 index 7c82beb0..00000000 --- a/doc/examples/sysv-args.m4 +++ /dev/null @@ -1,14 +0,0 @@ -divert(-1) -define(`nargs', `$#') -define(`concat', `ifelse(1, $#, `$1', `$1` 'concat(shift($@))')') -traceon(`concat', `nargs') -divert - -nargs -nargs() -nargs(1,2,3,4,5,6) - -concat() -concat(`hej', `med', `dig') -concat(`hej', `med', `dig', `en gang igen') -concat(an, awful, lot, of, argument, at, least, more, that, ten, silly, arguments) diff --git a/doc/examples/time.m4 b/doc/examples/time.m4 deleted file mode 100644 index ae931049..00000000 --- a/doc/examples/time.m4 +++ /dev/null @@ -1,21 +0,0 @@ -dnl Copyright (C) 2006, 2010, 2013-2014, 2017 Free Software Foundation, -dnl Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it -dnl with or without modifications, as long as this notice is preserved. -load(`time') - -`currenttime' = currenttime -`ctime' = ctime != ctime(eval(currenttime+60*60*24)) -gmtime = gmtime(currenttime) -localtime = localtime(currenttime) -define(`q', `$1,$2,$3,$4,$5,$6,$9')dnl - -currenttime -eval(currenttime+60*60*24) -localtime(eval(currenttime+60*60*24)) -q(localtime(eval(currenttime+60*60*24))) -mktime = mktime(q(localtime(eval(currenttime+60*60*24)))) - -%A %B %d, %Y = strftime(`%A %B %d, %Y', currenttime) -%X on %x = strftime(`%X on %x', currenttime) diff --git a/doc/examples/time2.m4 b/doc/examples/time2.m4 deleted file mode 100644 index 36840c4f..00000000 --- a/doc/examples/time2.m4 +++ /dev/null @@ -1,19 +0,0 @@ -dnl Copyright (C) 2006, 2010, 2013-2014, 2017 Free Software Foundation, -dnl Inc. -dnl This file is free software; the Free Software Foundation -dnl gives unlimited permission to copy and/or distribute it -dnl with or without modifications, as long as this notice is preserved. -`currenttime' = currenttime -`ctime' = ctime != ctime(eval(currenttime+60*60*24)) -gmtime = gmtime(currenttime) -localtime = localtime(currenttime) -define(`q', `$1,$2,$3,$4,$5,$6,$9')dnl - -currenttime -eval(currenttime+60*60*24) -localtime(eval(currenttime+60*60*24)) -q(localtime(eval(currenttime+60*60*24))) -mktime = mktime(q(localtime(eval(currenttime+60*60*24)))) - -%A %B %d, %Y = strftime(`%A %B %d, %Y', currenttime) -%X on %x = strftime(`%X on %x', currenttime) diff --git a/doc/examples/trace.m4 b/doc/examples/trace.m4 deleted file mode 100644 index 92ce9816..00000000 --- a/doc/examples/trace.m4 +++ /dev/null @@ -1,30 +0,0 @@ -divert(-1) - -# move(from, to) -define(`move', `Move one disk from `$1' to `$2'. -') - -# _hanoi (cnt, from, to, aux) -define(`_hanoi', `ifelse(eval(`$1'<=1), 1, `move($2, $3)', -`$0(decr($1), $2, $4, $3)move($2, $3)$0(decr($1), $4, $3, $2)')') - -# hanoi (cnt) -define(`hanoi', `_$0(`$1', source, destination, auxilliary)') -divert`'dnl - -# Debugmode t -debugmode(`t') -hanoi(2) - -# Debugmode taeq -debugmode(`taeq') -hanoi(2) - -# Debugmode OFF -debugmode -hanoi(2) - -# Debugmode ae -debugmode(`ae') -traceon(`move', `_hanoi') -hanoi(2) diff --git a/doc/examples/translit.m4 b/doc/examples/translit.m4 deleted file mode 100644 index 078d1726..00000000 --- a/doc/examples/translit.m4 +++ /dev/null @@ -1,8 +0,0 @@ -# traceon(`translit')dnl -translit(`GNUs not Unix', `a-z') -translit(`GNUs not Unix', `a-z', `A-Z') -translit(`GNUs not Unix', `A-Z', `a-z') -translit(`GNUs not Unix', `A-Z') -translit(`a-z', `a-') -translit(`A-Z', `A-Z-', `-A-Z') -translit(`GNUs not Unix', `Z-A', `a-z') diff --git a/doc/examples/undivert.incl b/doc/examples/undivert.incl deleted file mode 100644 index 408e0e20..00000000 --- a/doc/examples/undivert.incl +++ /dev/null @@ -1 +0,0 @@ -This is to be undiverted soon. diff --git a/doc/examples/undivert.m4 b/doc/examples/undivert.m4 deleted file mode 100644 index 61dfb391..00000000 --- a/doc/examples/undivert.m4 +++ /dev/null @@ -1,5 +0,0 @@ -define(`undiverted', `UNDIVERTED') -# undiverted file. -undivert(`undivert.incl') -# included file. -include(`undivert.incl') diff --git a/doc/examples/wrap.m4 b/doc/examples/wrap.m4 deleted file mode 100644 index bbe7ae0b..00000000 --- a/doc/examples/wrap.m4 +++ /dev/null @@ -1,10 +0,0 @@ -divert(-1) -m4wrap(`Wrapper no. 1 -') - -m4wrap(`Wrapper no. 2 -m4wrap(`Wrapper no. 3 -m4wrap(`Wrapper no. 4 -')')') -divert -No. 33: The End. diff --git a/doc/examples/wrapfifo.m4 b/doc/examples/wrapfifo.m4 deleted file mode 100644 index 95ff87a0..00000000 --- a/doc/examples/wrapfifo.m4 +++ /dev/null @@ -1,10 +0,0 @@ -dnl Redefine m4wrap to have FIFO semantics. -define(`_m4wrap_level', `0')dnl -define(`m4wrap', -`ifdef(`m4wrap'_m4wrap_level, - `define(`m4wrap'_m4wrap_level, - defn(`m4wrap'_m4wrap_level)`$1')', - `builtin(`m4wrap', `define(`_m4wrap_level', - incr(_m4wrap_level))dnl -m4wrap'_m4wrap_level)dnl -define(`m4wrap'_m4wrap_level, `$1')')')dnl diff --git a/doc/examples/wraplifo.m4 b/doc/examples/wraplifo.m4 deleted file mode 100644 index bdbf3fb6..00000000 --- a/doc/examples/wraplifo.m4 +++ /dev/null @@ -1,10 +0,0 @@ -dnl Redefine m4wrap to have LIFO semantics. -define(`_m4wrap_level', `0')dnl -define(`_m4wrap', defn(`m4wrap'))dnl -define(`m4wrap', -`ifdef(`m4wrap'_m4wrap_level, - `define(`m4wrap'_m4wrap_level, - `$1'defn(`m4wrap'_m4wrap_level))', - `_m4wrap(`define(`_m4wrap_level', incr(_m4wrap_level))dnl -m4wrap'_m4wrap_level)dnl -define(`m4wrap'_m4wrap_level, `$1')')')dnl diff --git a/doc/examples/wraplifo2.m4 b/doc/examples/wraplifo2.m4 deleted file mode 100644 index 5b450a76..00000000 --- a/doc/examples/wraplifo2.m4 +++ /dev/null @@ -1,9 +0,0 @@ -dnl Redefine m4wrap to have LIFO semantics, improved example. -include(`join.m4')dnl -define(`_m4wrap', defn(`m4wrap'))dnl -define(`_arg1', `$1')dnl -define(`m4wrap', -`ifdef(`_$0_text', - `define(`_$0_text', joinall(` ', $@)defn(`_$0_text'))', - `_$0(`_arg1(defn(`_$0_text')undefine(`_$0_text'))')dnl -define(`_$0_text', joinall(` ', $@))')')dnl diff --git a/doc/m4.texi b/doc/m4.texi deleted file mode 100644 index 5108e20e..00000000 --- a/doc/m4.texi +++ /dev/null @@ -1,10411 +0,0 @@ -\input texinfo @c -*- texinfo -*- -@comment ======================================================== -@comment %**start of header -@setfilename m4.info -@include version.texi -@settitle GNU M4 @value{VERSION} macro processor -@setchapternewpage odd -@finalout - -@set beta - -@c @tabchar{} -@c ---------- -@c The testsuite expects literal tab output in some examples, but -@c literal tabs in texinfo leads to formatting issues. -@macro tabchar -@ @c -@end macro - -@c @ovar{ARG} -@c ------------------- -@c The ARG is an optional argument. To be used for macro arguments in -@c their documentation (@defmac). -@macro ovar{varname} -@r{[}@var{\varname\}@r{]}@c -@end macro - -@c @dvar{ARG, DEFAULT} -@c ------------------- -@c The ARG is an optional argument, defaulting to DEFAULT. To be used -@c for macro arguments in their documentation (@defmac). -@macro dvar{varname, default} -@r{[}@var{\varname\} = @samp{\default\}@r{]}@c -@end macro - -@comment %**end of header -@comment ======================================================== - -@copying - -This manual (@value{UPDATED}) is for GNU M4 (version -@value{VERSION}), a package containing an implementation of the m4 macro -language. - -Copyright @copyright{} 1989-1994, 2004-2011, 2013-2014, 2017 Free -Software Foundation, Inc. - -@quotation -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU Free Documentation License, -Version 1.3 or any later version published by the Free Software -Foundation; with no Invariant Sections, no Front-Cover Texts, and no -Back-Cover Texts. A copy of the license is included in the section -entitled ``GNU Free Documentation License.'' -@end quotation -@end copying - -@dircategory Text creation and manipulation -@direntry -* M4: (m4). A powerful macro processor. -@end direntry - -@titlepage -@title GNU M4, version @value{VERSION} -@subtitle A powerful macro processor -@subtitle Edition @value{EDITION}, @value{UPDATED} -@author by Ren@'e Seindal, Fran@,{c}ois Pinard, -@author Gary V. Vaughan, and Eric Blake -@author (@email{bug-m4@@gnu.org}) - -@page -@vskip 0pt plus 1filll -@insertcopying -@end titlepage - -@contents - -@ifnottex -@node Top -@top GNU M4 -@insertcopying -@end ifnottex - -GNU @code{m4} is an implementation of the traditional UNIX macro -processor. It is mostly SVR4 compatible, although it has some -extensions (for example, handling more than 9 positional parameters -to macros). @code{m4} also has builtin functions for including -files, running shell commands, doing arithmetic, etc. Autoconf needs -GNU @code{m4} for generating @file{configure} scripts, but not for -running them. - -GNU @code{m4} was originally written by Ren@'e Seindal, with -subsequent changes by Fran@,{c}ois Pinard and other volunteers -on the Internet. All names and email addresses can be found in the -files @file{m4-@value{VERSION}/@/AUTHORS} and -@file{m4-@value{VERSION}/@/THANKS} from the GNU M4 -distribution. - -@ifclear beta -This is release @value{VERSION}. It is now considered stable: future -releases on this branch are only meant to fix bugs, increase speed, or -improve documentation. -@end ifclear - -@ifset beta -This is BETA release @value{VERSION}. This is a development release, -and as such, is prone to bugs, crashes, unforeseen features, incomplete -documentation@dots{}, therefore, use at your own peril. In case of -problems, please do not hesitate to report them (see the -@file{m4-@value{VERSION}/@/README} file in the distribution). -@xref{Experiments}. -@end ifset - -@menu -* Preliminaries:: Introduction and preliminaries -* Invoking m4:: Invoking @code{m4} -* Syntax:: Lexical and syntactic conventions - -* Macros:: How to invoke macros -* Definitions:: How to define new macros -* Conditionals:: Conditionals, loops, and recursion - -* Debugging:: How to debug macros and input - -* Input Control:: Input control -* File Inclusion:: File inclusion -* Diversions:: Diverting and undiverting output - -* Modules:: Extending M4 with dynamic runtime modules - -* Text handling:: Macros for text handling -* Arithmetic:: Macros for doing arithmetic -* Shell commands:: Macros for running shell commands -* Miscellaneous:: Miscellaneous builtin macros -* Frozen files:: Fast loading of frozen state - -* Compatibility:: Compatibility with other versions of @code{m4} -* Answers:: Correct version of some examples - -* Copying This Package:: How to make copies of the overall M4 package -* Copying This Manual:: How to make copies of this manual -* Indices:: Indices of concepts and macros - -@detailmenu - --- The Detailed Node Listing --- - -Introduction and preliminaries - -* Intro:: Introduction to @code{m4} -* History:: Historical references -* Bugs:: Problems and bugs -* Manual:: Using this manual - -Invoking @code{m4} - -* Operation modes:: Command line options for operation modes -* Preprocessor features:: Command line options for preprocessor features -* Limits control:: Command line options for limits control -* Frozen state:: Command line options for frozen state -* Debugging options:: Command line options for debugging -* Command line files:: Specifying input files on the command line - -Lexical and syntactic conventions - -* Names:: Macro names -* Quoted strings:: Quoting input to @code{m4} -* Comments:: Comments in @code{m4} input -* Other tokens:: Other kinds of input tokens -* Input processing:: How @code{m4} copies input to output -* Regular expression syntax:: How @code{m4} interprets regular expressions - -How to invoke macros - -* Invocation:: Macro invocation -* Inhibiting Invocation:: Preventing macro invocation -* Macro Arguments:: Macro arguments -* Quoting Arguments:: On Quoting Arguments to macros -* Macro expansion:: Expanding macros - -How to define new macros - -* Define:: Defining a new macro -* Arguments:: Arguments to macros -* Pseudo Arguments:: Special arguments to macros -* Undefine:: Deleting a macro -* Defn:: Renaming macros -* Pushdef:: Temporarily redefining macros -* Renamesyms:: Renaming macros with regular expressions - -* Indir:: Indirect call of macros -* Builtin:: Indirect call of builtins -* M4symbols:: Getting the defined macro names - -Conditionals, loops, and recursion - -* Ifdef:: Testing if a macro is defined -* Ifelse:: If-else construct, or multibranch -* Shift:: Recursion in @code{m4} -* Forloop:: Iteration by counting -* Foreach:: Iteration by list contents -* Stacks:: Working with definition stacks -* Composition:: Building macros with macros - -How to debug macros and input - -* Dumpdef:: Displaying macro definitions -* Trace:: Tracing macro calls -* Debugmode:: Controlling debugging options -* Debuglen:: Limiting debug output -* Debugfile:: Saving debugging output - -Input control - -* Dnl:: Deleting whitespace in input -* Changequote:: Changing the quote characters -* Changecom:: Changing the comment delimiters -* Changeresyntax:: Changing the regular expression syntax -* Changesyntax:: Changing the lexical structure of the input -* M4wrap:: Saving text until end of input - -File inclusion - -* Include:: Including named files -* Search Path:: Searching for include files - -Diverting and undiverting output - -* Divert:: Diverting output -* Undivert:: Undiverting output -* Divnum:: Diversion numbers -* Cleardivert:: Discarding diverted text - -Extending M4 with dynamic runtime modules - -* M4modules:: Listing loaded modules -* Standard Modules:: Standard bundled modules - -Macros for text handling - -* Len:: Calculating length of strings -* Index macro:: Searching for substrings -* Regexp:: Searching for regular expressions -* Substr:: Extracting substrings -* Translit:: Translating characters -* Patsubst:: Substituting text by regular expression -* Format:: Formatting strings (printf-like) - -Macros for doing arithmetic - -* Incr:: Decrement and increment operators -* Eval:: Evaluating integer expressions -* Mpeval:: Multiple precision arithmetic - -Macros for running shell commands - -* Platform macros:: Determining the platform -* Syscmd:: Executing simple commands -* Esyscmd:: Reading the output of commands -* Sysval:: Exit status -* Mkstemp:: Making temporary files -* Mkdtemp:: Making temporary directories - -Miscellaneous builtin macros - -* Errprint:: Printing error messages -* Location:: Printing current location -* M4exit:: Exiting from @code{m4} -* Syncoutput:: Turning on and off sync lines - -Fast loading of frozen state - -* Using frozen files:: Using frozen files -* Frozen file format 1:: Frozen file format 1 -* Frozen file format 2:: Frozen file format 2 - -Compatibility with other versions of @code{m4} - -* Extensions:: Extensions in GNU M4 -* Incompatibilities:: Other incompatibilities -* Experiments:: Experimental features in GNU M4 - -Correct version of some examples - -* Improved exch:: Solution for @code{exch} -* Improved forloop:: Solution for @code{forloop} -* Improved foreach:: Solution for @code{foreach} -* Improved copy:: Solution for @code{copy} -* Improved m4wrap:: Solution for @code{m4wrap} -* Improved cleardivert:: Solution for @code{cleardivert} -* Improved capitalize:: Solution for @code{capitalize} -* Improved fatal_error:: Solution for @code{fatal_error} - -How to make copies of the overall M4 package - -* GNU General Public License:: License for copying the M4 package - -How to make copies of this manual - -* GNU Free Documentation License:: License for copying this manual - -Indices of concepts and macros - -* Macro index:: Index for all @code{m4} macros -* Concept index:: Index for many concepts - -@end detailmenu -@end menu - -@node Preliminaries -@chapter Introduction and preliminaries - -This first chapter explains what GNU @code{m4} is, where @code{m4} -comes from, how to read and use this documentation, how to call the -@code{m4} program, and how to report bugs about it. It concludes by -giving tips for reading the remainder of the manual. - -The following chapters then detail all the features of the @code{m4} -language, as shipped in the GNU M4 package. - -@menu -* Intro:: Introduction to @code{m4} -* History:: Historical references -* Bugs:: Problems and bugs -* Manual:: Using this manual -@end menu - -@node Intro -@section Introduction to @code{m4} - -@cindex overview of @code{m4} -@code{m4} is a macro processor, in the sense that it copies its -input to the output, expanding macros as it goes. Macros are either -builtin or user-defined, and can take any number of arguments. -Besides just doing macro expansion, @code{m4} has builtin functions -for including named files, running shell commands, doing integer -arithmetic, manipulating text in various ways, performing recursion, -etc.@dots{} @code{m4} can be used either as a front-end to a compiler, -or as a macro processor in its own right. - -The @code{m4} macro processor is widely available on all UNIXes, and has -been standardized by POSIX. -Usually, only a small percentage of users are aware of its existence. -However, those who find it often become committed users. The -popularity of GNU Autoconf, which requires GNU -@code{m4} for @emph{generating} @file{configure} scripts, is an incentive -for many to install it, while these people will not themselves -program in @code{m4}. GNU @code{m4} is mostly compatible with the -System V, Release 4 version, except for some minor differences. -@xref{Compatibility}, for more details. - -Some people find @code{m4} to be fairly addictive. They first use -@code{m4} for simple problems, then take bigger and bigger challenges, -learning how to write complex sets of @code{m4} macros along the way. -Once really addicted, users pursue writing of sophisticated @code{m4} -applications even to solve simple problems, devoting more time -debugging their @code{m4} scripts than doing real work. Beware that -@code{m4} may be dangerous for the health of compulsive programmers. - -@node History -@section Historical references - -@cindex history of @code{m4} -@cindex GNU M4, history of -Macro languages were invented early in the history of computing. In the -1950s Alan Perlis suggested that the macro language be independent of the -language being processed. Techniques such as conditional and recursive -macros, and using macros to define other macros, were described by Doug -McIlroy of Bell Labs in ``Macro Instruction Extensions of Compiler -Languages'', @emph{Communications of the ACM} 3, 4 (1960), 214--20, -@url{http://dx.doi.org/10.1145/367177.367223}. - -An important precursor of @code{m4} was GPM; see C. Strachey, -@c The title uses lower case and has no space between "macro" and "generator". -``A general purpose macrogenerator'', @emph{Computer Journal} 8, 3 -(1965), 225--41, @url{http://dx.doi.org/10.1093/comjnl/8.3.225}. GPM is -also succinctly described in David Gries's book @emph{Compiler -Construction for Digital Computers}, Wiley (1971). Strachey was a -brilliant programmer: GPM fit into 250 machine instructions! - -Inspired by GPM while visiting Strachey's Lab in 1968, McIlroy wrote a -model preprocessor in that fit into a page of Snobol 3 code, and McIlroy -and Robert Morris developed a series of further models at Bell Labs. -Andrew D. Hall followed up with M6, a general purpose macro processor -used to port the Fortran source code of the Altran computer algebra -system; see Hall's ``The M6 Macro Processor'', Computing Science -Technical Report #2, Bell Labs (1972), -@url{http://cm.bell-labs.com/cm/cs/cstr/2.pdf}. M6's source code -consisted of about 600 Fortran statements. Its name was the first of -the @code{m4} line. - -The Brian Kernighan and P.J. Plauger book @emph{Software Tools}, -Addison-Wesley (1976), describes and implements a Unix -macro-processor language, which inspired Dennis Ritchie to write -@code{m3}, a macro processor for the AP-3 minicomputer. - -Kernighan and Ritchie then joined forces to develop the original -@code{m4}, described in ``The M4 Macro Processor'', Bell Laboratories -(1977), @url{http://wolfram.schneider.org/bsd/7thEdManVol2/m4/m4.pdf}. -It had only 21 builtin macros. - -While @code{GPM} was more @emph{pure}, @code{m4} is meant to deal with -the true intricacies of real life: macros can be recognized without -being pre-announced, skipping whitespace or end-of-lines is easier, -more constructs are builtin instead of derived, etc. - -Originally, the Kernighan and Plauger macro-processor, and then -@code{m3}, formed the engine for the Rational FORTRAN preprocessor, -that is, the @code{Ratfor} equivalent of @code{cpp}. Later, @code{m4} -was used as a front-end for @code{Ratfor}, @code{C} and @code{Cobol}. - -Ren@'e Seindal released his implementation of @code{m4}, GNU -@code{m4}, -in 1990, with the aim of removing the artificial limitations in many -of the traditional @code{m4} implementations, such as maximum line -length, macro size, or number of macros. - -The late Professor A. Dain Samples described and implemented a further -evolution in the form of @code{M5}: ``User's Guide to the M5 Macro -Language: 2nd edition'', Electronic Announcement on comp.compilers -newsgroup (1992). - -Fran@,{c}ois Pinard took over maintenance of GNU @code{m4} in -1992, until 1994 when he released GNU @code{m4} 1.4, which was -the stable release for 10 years. It was at this time that GNU -Autoconf decided to require GNU @code{m4} as its underlying -engine, since all other implementations of @code{m4} had too many -limitations. - -More recently, in 2004, Paul Eggert released 1.4.1 and 1.4.2 which -addressed some long standing bugs in the venerable 1.4 release. Then in -2005, Gary V. Vaughan collected together the many patches to -GNU @code{m4} 1.4 that were floating around the net and -released 1.4.3 and 1.4.4. And in 2006, Eric Blake joined the team and -prepared patches for the release of 1.4.5, 1.4.6, 1.4.7, and 1.4.8. -More bug fixes were incorporated in 2007, with releases 1.4.9 and -1.4.10. Eric continued with some portability fixes for 1.4.11 and -1.4.12 in 2008, 1.4.13 in 2009, 1.4.14 and 1.4.15 in 2010, and 1.4.16 -in 2011. Following a long hiatus, Gary released 1.4.17 after upgrading -to the latest autotools (and gnulib) along with all the small fixes they -had accumulated. - -Additionally, in 2008, Eric rewrote the scanning engine to reduce -recursive evaluation from quadratic to linear complexity. This was -released as M4 1.6 in 2009. The 1.x branch series remains open for bug -fixes. - -Meanwhile, development was underway for new features for @code{m4}, -such as dynamic module loading and additional builtins, practically -rewriting the entire code base. This development has spurred -improvements to other GNU software, such as GNU -Libtool. GNU M4 2.0 is the result of this effort. - -@node Bugs -@section Problems and bugs - -@cindex reporting bugs -@cindex bug reports -@cindex suggestions, reporting -If you have problems with GNU M4 or think you've found a bug, -please report it. Before reporting a bug, make sure you've actually -found a real bug. Carefully reread the documentation and see if it -really says you can do what you're trying to do. If it's not clear -whether you should be able to do something or not, report that too; it's -a bug in the documentation! - -Before reporting a bug or trying to fix it yourself, try to isolate it -to the smallest possible input file that reproduces the problem. Then -send us the input file and the exact results @code{m4} gave you. Also -say what you expected to occur; this will help us decide whether the -problem was really in the documentation. - -Once you've got a precise problem, send e-mail to -@email{bug-m4@@gnu.org}. Please include the version number of @code{m4} -you are using. You can get this information with the command -@kbd{m4 --version}. You can also run @kbd{make check} to generate the -file @file{tests/@/testsuite.log}, useful for including in your report. - -Non-bug suggestions are always welcome as well. If you have questions -about things that are unclear in the documentation or are just obscure -features, please report them too. - -@node Manual -@section Using this manual - -@cindex examples, understanding -This manual contains a number of examples of @code{m4} input and output, -and a simple notation is used to distinguish input, output and error -messages from @code{m4}. Examples are set out from the normal text, and -shown in a fixed width font, like this - -@comment ignore -@example -This is an example of an example! -@end example - -To distinguish input from output, all output from @code{m4} is prefixed -by the string @samp{@result{}}, and all error messages by the string -@samp{@error{}}. When showing how command line options affect matters, -the command line is shown with a prompt @samp{$ @kbd{like this}}, -otherwise, you can assume that a simple @kbd{m4} invocation will work. -Thus: - -@comment ignore -@example -$ @kbd{command line to invoke m4} -Example of input line -@result{}Output line from m4 -@error{}and an error message -@end example - -The sequence @samp{^D} in an example indicates the end of the input -file. The sequence @samp{@key{NL}} refers to the newline character. -The majority of these examples are self-contained, and you can run them -with similar results. In fact, the testsuite that is bundled in the -GNU M4 package consists in part of the examples -in this document! Some of the examples assume that your current -directory is located where you unpacked the installation, so if you plan -on following along, you may find it helpful to do this now: - -@comment ignore -@example -$ @kbd{cd m4-@value{VERSION}} -@end example - -As each of the predefined macros in @code{m4} is described, a prototype -call of the macro will be shown, giving descriptive names to the -arguments, e.g., - -@deffn {Composite (none)} example (@var{string}, @dvar{count, 1}, @ - @ovar{argument}@dots{}) -This is a sample prototype. There is not really a macro named -@code{example}, but this documents that if there were, it would be a -Composite macro, rather than a Builtin, and would be provided by the -module @code{none}. - -It requires at least one argument, @var{string}. Remember that in -@code{m4}, there must not be a space between the macro name and the -opening parenthesis, unless it was intended to call the macro without -any arguments. The brackets around @var{count} and @var{argument} show -that these arguments are optional. If @var{count} is omitted, the macro -behaves as if count were @samp{1}, whereas if @var{argument} is omitted, -the macro behaves as if it were the empty string. A blank argument is -not the same as an omitted argument. For example, @samp{example(`a')}, -@samp{example(`a',`1')}, and @samp{example(`a',`1',)} would behave -identically with @var{count} set to @samp{1}; while @samp{example(`a',)} -and @samp{example(`a',`')} would explicitly pass the empty string for -@var{count}. The ellipses (@samp{@dots{}}) show that the macro -processes additional arguments after @var{argument}, rather than -ignoring them. -@end deffn - -Each builtin definition will list, in parentheses, the module that must -be loaded to use that macro. The standard modules include -@samp{m4} (which is always available), @samp{gnu} (for GNU specific -m4 extensions), and @samp{traditional} (for compatibility with System V -m4). @xref{Modules}. - -@cindex numbers -All macro arguments in @code{m4} are strings, but some are given -special interpretation, e.g., as numbers, file names, regular -expressions, etc. The documentation for each macro will state how the -parameters are interpreted, and what happens if the argument cannot be -parsed according to the desired interpretation. Unless specified -otherwise, a parameter specified to be a number is parsed as a decimal, -even if the argument has leading zeros; and parsing the empty string as -a number results in 0 rather than an error, although a warning will be -issued. - -This document consistently writes and uses @dfn{builtin}, without a -hyphen, as if it were an English word. This is how the @code{builtin} -primitive is spelled within @code{m4}. - -@node Invoking m4 -@chapter Invoking @code{m4} - -@cindex command line -@cindex invoking @code{m4} -The format of the @code{m4} command is: - -@comment ignore -@example -@code{m4} @r{[}@var{option}@dots{}@r{]} @r{[}@var{file}@dots{}@r{]} -@end example - -@cindex command line, options -@cindex options, command line -@cindex @env{POSIXLY_CORRECT} -All options begin with @samp{-}, or if long option names are used, with -@samp{--}. A long option name need not be written completely, any -unambiguous prefix is sufficient. POSIX requires @code{m4} to -recognize arguments intermixed with files, even when -@env{POSIXLY_CORRECT} is set in the environment. Most options take -effect at startup regardless of their position, but some are documented -below as taking effect after any files that occurred earlier in the -command line. The argument @option{--} is a marker to denote the end of -options. - -With short options, options that do not take arguments may be combined -into a single command line argument with subsequent options, options -with mandatory arguments may be provided either as a single command line -argument or as two arguments, and options with optional arguments must -be provided as a single argument. In other words, -@kbd{m4 -QPDfoo -d a -d+f} is equivalent to -@kbd{m4 -Q -P -D foo -d ./a -d+f}, although the latter form is -considered canonical. - -With long options, options with mandatory arguments may be provided with -an equal sign (@samp{=}) in a single argument, or as two arguments, and -options with optional arguments must be provided as a single argument. -In other words, @kbd{m4 --def foo --debug a} is equivalent to -@kbd{m4 --define=foo --debug= -- ./a}, although the latter form is -considered canonical (not to mention more robust, in case a future -version of @code{m4} introduces an option named @option{--default}). - -@code{m4} understands the following options, grouped by functionality. - -@menu -* Operation modes:: Command line options for operation modes -* Preprocessor features:: Command line options for preprocessor features -* Limits control:: Command line options for limits control -* Frozen state:: Command line options for frozen state -* Debugging options:: Command line options for debugging -* Command line files:: Specifying input files on the command line -@end menu - -@node Operation modes -@section Command line options for operation modes - -Several options control the overall operation of @code{m4}: - -@table @code -@item --help -Print a help summary on standard output, then immediately exit -@code{m4} without reading any input files or performing any other -actions. - -@item --version -Print the version number of the program on standard output, then -immediately exit @code{m4} without reading any input files or -performing any other actions. - -@item -b -@itemx --batch -Makes this invocation of @code{m4} non-interactive. This means that -output will be buffered, and an interrupt or pipe write error will halt -execution. If neither -@option{-b} nor @option{-i} are specified, this is activated by default -when any input files are specified, or when either standard input or -standard error is not a terminal. Note that this means that @kbd{m4} -alone might be interactive, but @kbd{m4 -} is not, even though both -commands process only standard input. If both @option{-b} and -@option{-i} are specified, only the last one takes effect. - -@item -c -@itemx --discard-comments -Discard all comments instead of copying them to the output. - -@item -E -@itemx --fatal-warnings -@cindex errors, fatal -@cindex fatal errors -Controls the effect of warnings. If unspecified, then execution -continues and exit status is unaffected when a warning is printed. If -specified exactly once, warnings become fatal; when one is issued, -execution continues, but the exit status will be non-zero. If specified -multiple times, then execution halts with non-zero status the first time -a warning is issued. The introduction of behavior levels is new to M4 -1.4.9; for behavior consistent with earlier versions, you should specify -@option{-E} twice. - - -For backwards compatibility reasons, using @option{-E} behaves as if an -implicit @option{--debug=-d} option is also present. This is so that -scripts written for older M4 versions will not fail if they used -constructs that were previously silently allowed, but would now trigger -a warning. - -@example -$ @kbd{m4} -defn(`oops') -@error{}m4:stdin:1: warning: defn: undefined macro 'oops' -@result{} -^D -@end example - -@comment ignore -@example -$ @kbd{echo $?} -@result{}0 -@end example - -@comment options: -E -@example -$ @kbd{m4 -E} -defn(`oops') -@result{} -^D -@end example - -@comment ignore -@example -$ @kbd{echo $?} -@result{}0 -@end example - -@comment options: -E -d -@comment status: 1 -@example -$ @kbd{m4 -E -d} -defn(`oops') -@error{}m4:stdin:1: warning: defn: undefined macro 'oops' -@result{} -^D -@end example - -@comment ignore -@example -$ @kbd{echo $?} -@result{}1 -@end example - -@item -i -@itemx --interactive -@itemx -e -Makes this invocation of @code{m4} interactive. This means that all -output will be unbuffered, interrupts will be ignored, and behavior on -pipe write errors is inherited from the parent process. If neither -@option{-b} nor @option{-i} are specified, this is activated by default -when no input files are specified, and when both standard input and -standard error are terminals (similar to the way that /bin/sh determines -when to be interactive). If both @option{-b} and @option{-i} are -specified, only the last one takes effect. The spelling @option{-e} -exists for compatibility with other @code{m4} implementations, and -issues a warning because it may be withdrawn in a future version of -GNU M4. - -@item -P -@itemx --prefix-builtins -Internally modify @emph{all} builtin macro names so they all start with -the prefix @samp{m4_}. For example, using this option, one should write -@samp{m4_define} instead of @samp{define}, and @samp{@w{m4___file__}} -instead of @samp{@w{__file__}}. This option has no effect if @option{-R} -is also specified. - -@item -Q -@itemx --quiet -@itemx --silent -Suppress warnings, such as missing or superfluous arguments in macro -calls, or treating the empty string as zero. Error messages are still -printed. The distinction between error and warning is fuzzy, and if -you encounter a situation where the message output did not match your -expectations, please report that as a bug. This option is implied if -@env{POSIXLY_CORRECT} is set in the environment. - -@item -r@r{[}@var{resyntax-spec}@r{]} -@itemx --regexp-syntax@r{[}=@var{resyntax-spec}@r{]} -Set the regular expression syntax according to @var{resyntax-spec}. -When this option is not given, or @var{resyntax-spec} is omitted, -GNU M4 uses the flavor @code{GNU_M4}, which provides -emacs-compatible regular expressions. @xref{Changeresyntax}, for more -details on the format and meaning of @var{resyntax-spec}. This option -may be given more than once, and order with respect to file names is -significant. - -@item --safer -Cripple the following builtins, since each can perform potentially -unsafe actions: @code{maketemp}, @code{mkstemp} (@pxref{Mkstemp}), -@code{mkdtemp} (@pxref{Mkdtemp}), @code{debugfile} (@pxref{Debugfile}), -@code{syscmd} (@pxref{Syscmd}), and @code{esyscmd} (@pxref{Esyscmd}). -An attempt to use any of these macros will result in an error. This -option is intended to make it safer to preprocess an input file of -unknown origin. - -@item -W -@itemx --warnings -Enable warnings. Warnings are on by default unless -@env{POSIXLY_CORRECT} was set in the environment; this option exists to -allow overriding @option{--silent}. -@comment FIXME should we accept -Wall, -Wnone, -Wcategory, -@comment -Wno-category...? -@end table - -@node Preprocessor features -@section Command line options for preprocessor features - -@cindex macro definitions, on the command line -@cindex command line, macro definitions on the -@cindex preprocessor features -Several options allow @code{m4} to behave more like a preprocessor. -Macro definitions and deletions can be made on the command line, the -search path can be altered, and the output file can track where the -input came from. These features occur with the following options: - -@table @code -@item -B @var{directory} -@itemx --prepend-include=@var{directory} -Make @code{m4} search @var{directory} for included files, prior to -searching the current working directory. @xref{Search Path}, for more -details. This option may be given more than once. Some other -implementations of @code{m4} use @option{-B @var{number}} to change their -hard-coded limits, but that is unnecessary in GNU where the -only limit is your hardware capability. So although it is unlikely that -you will want to include a relative directory whose name is purely -numeric, GNU @code{m4} will warn you about this potential -compatibility issue; you can avoid the warning by using the long -spelling, or by using @samp{./@var{number}} if you really meant it. - -@item -D @var{name}@r{[}=@var{value}@r{]} -@itemx --define=@var{name}@r{[}=@var{value}@r{]} -This enters @var{name} into the symbol table. If @samp{=@var{value}} is -missing, the value is taken to be the empty string. The @var{value} can -be any string, and the macro can be defined to take arguments, just as -if it was defined from within the input. This option may be given more -than once; order with respect to file names is significant, and -redefining the same @var{name} loses the previous value. - -@item --import-environment -Imports every variable in the environment as a macro. This is done -before @option{-D} and @option{-U}, so they can override the -environment. - -@item -I @var{directory} -@itemx --include=@var{directory} -Make @code{m4} search @var{directory} for included files that are not -found in the current working directory. @xref{Search Path}, for more -details. This option may be given more than once. - -@item --popdef=@var{name} -This deletes the top-most meaning @var{name} might have. Obviously, -only predefined macros can be deleted in this way. This option may be -given more than once; popping a @var{name} that does not have a -definition is silently ignored. Order is significant with respect to -file names. - -@item -p @var{name}@r{[}=@var{value}@r{]} -@itemx --pushdef=@var{name}@r{[}=@var{value}@r{]} -This enters @var{name} into the symbol table. If @samp{=@var{value}} is -missing, the value is taken to be the empty string. The @var{value} can -be any string, and the macro can be defined to take arguments, just as -if it was defined from within the input. This option may be given more -than once; order with respect to file names is significant, and -redefining the same @var{name} adds another definition to its stack. - -@item -s -@itemx --synclines -Short for @option{--syncoutput=1}, turning on synchronization lines -(sometimes called @dfn{synclines}). - -@item --syncoutput@r{[}=@var{state}@r{]} -@cindex synchronization lines -@cindex location, input -@cindex input location -Control the generation of synchronization lines from the command line. -Synchronization lines are for use by the C preprocessor or other -similar tools. Order is significant with respect to file names. This -option is useful, for example, when @code{m4} is used as a -front end to a compiler. Source file name and line number information -is conveyed by directives of the form @samp{#line @var{linenum} -"@var{file}"}, which are inserted as needed into the middle of the -output. Such directives mean that the following line originated or was -expanded from the contents of input file @var{file} at line -@var{linenum}. The @samp{"@var{file}"} part is often omitted when -the file name did not change from the previous directive. - -Synchronization directives are always given on complete lines by -themselves. When a synchronization discrepancy occurs in the middle of -an output line, the associated synchronization directive is delayed -until the next newline that does not occur in the middle of a quoted -string or comment. @xref{Syncoutput}, for runtime control. @var{state} -is interpreted the same as the argument to @code{syncoutput}; if -@var{state} is omitted, or @option{--syncoutput} is not used, -synchronization lines are disabled. - -@item -U @var{name} -@itemx --undefine=@var{name} -This deletes any predefined meaning @var{name} might have. Obviously, -only predefined macros can be deleted in this way. This option may be -given more than once; undefining a @var{name} that does not have a -definition is silently ignored. Order is significant with respect to -file names. -@end table - -@node Limits control -@section Command line options for limits control - -There are some limits within @code{m4} that can be tuned. For -compatibility, @code{m4} also accepts some options that control limits -in other implementations, but which are automatically unbounded (limited -only by your hardware and operating system constraints) in GNU -@code{m4}. - -@table @code -@item -g -@itemx --gnu -Enable all the extensions in this implementation. This is on by -default unless @env{POSIXLY_CORRECT} is set in the environment; it -exists to allow overriding @option{--traditional}. - -@item -G -@itemx --posix -@itemx --traditional -Suppress all the extensions made in this implementation, compared to the -System V version. @xref{Compatibility}, for a list of these. This -loads the @samp{traditional} module in place of the @samp{gnu} module. -It is implied if @env{POSIXLY_CORRECT} is set in the environment. - -@item -L @var{num} -@itemx --nesting-limit=@var{num} -@cindex nesting limit -@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 -unlimited; but then heavily nested code could potentially cause a stack -overflow. @var{num} can have an optional scaling suffix. -@comment FIXME - need a node on what scaling suffixes are supported (see -@comment [info coreutils 'block size'] for ideas), and need to consider -@comment whether builtins should also understand scaling suffixes: -@comment eval, mpeval, perhaps format - -The precise effect of this option might be 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. - -@cindex rescanning -This option does @emph{not} have the ability to break endless -rescanning loops, since these do not necessarily consume much memory -or stack space. Through clever usage of rescanning loops, one can -request complex, time-consuming computations from @code{m4} with useful -results. Putting limitations in this area would break @code{m4} power. -There are many pathological cases: @w{@samp{define(`a', `a')a}} is -only the simplest example (but @pxref{Compatibility}). Expecting GNU -@code{m4} to detect these would be a little like expecting a compiler -system to detect and diagnose endless loops: it is a quite @emph{hard} -problem in general, if not undecidable! - -@item -H @var{num} -@itemx --hashsize=@var{num} -@itemx --word-regexp=@var{regexp} -These options are present only for compatibility with previous versions -of GNU @code{m4}. They do nothing except issue a warning, because the -symbol table size is not fixed anymore, and because the new -@code{changesyntax} feature is more efficient than the withdrawn -experimental @code{changeword}. These options will eventually disappear -in future releases. - -@item -S @var{num} -@itemx -T @var{num} -These options are present for compatibility with System V @code{m4}, but -do nothing in this implementation. They may disappear in future -releases, and issue a warning to that effect. -@end table - -@node Frozen state -@section Command line options for frozen state - -GNU @code{m4} comes with a feature of freezing internal state -(@pxref{Frozen files}). This can be used to speed up @code{m4} -execution when reusing a common initialization script. - -@table @code -@item -F @var{file} -@itemx --freeze-state=@var{file} -Once execution is finished, write out the frozen state on the specified -@var{file}. It is conventional, but not required, for @var{file} to end -in @samp{.m4f}. - -@item -R @var{file} -@itemx --reload-state=@var{file} -Before execution starts, recover the internal state from the specified -frozen @var{file}. The options @option{-D}, @option{-U}, @option{-t}, -@option{-m}, @option{-r}, and @option{--import-environment} take effect -after state is reloaded, but before the input files are read. -@end table - -@node Debugging options -@section Command line options for debugging - -Finally, there are several options for aiding in debugging @code{m4} -scripts. - -@table @code -@item -d@r{[}@r{[}-@r{|}+@r{]}@var{flags}@r{]} -@itemx --debug@r{[}=@r{[}-@r{|}+@r{]}@var{flags}@r{]} -@itemx --debugmode@r{[}=@r{[}-@r{|}+@r{]}@var{flags}@r{]} -Set the debug-level according to the flags @var{flags}. The debug-level -controls the format and amount of information presented by the debugging -functions. @xref{Debugmode}, for more details on the format and -meaning of @var{flags}. If omitted, @var{flags} defaults to -@samp{+adeq}. If the option occurs multiple times, @var{flags} starting -with @samp{-} or @samp{+} are cumulative, while @var{flags} starting -with a letter override all earlier settings. The debug-level starts -with @samp{d} enabled and all other flags disabled. To disable all -previously set flags, specify an explicit @var{flags} of @samp{-V}. For -backward compatibility reasons, the option @option{--fatal-warnings} -implies @samp{--debug=-d} as part of its effects. The spelling -@option{--debug} is recognized as an unambiguous option for -compatibility with earlier versions of GNU M4, but for -consistency with the builtin name, you can also use the spelling -@option{--debugmode}. Order is significant with respect to file names. - -The cumulative effect of the various options in this example is -equivalent to a single invocation of @code{debugmode(`adlqx')}: - -@comment options: -d-V -d+lx --debug --debugmode=-e -@example -$ @kbd{m4 -d+lx --debug --debugmode=-e} -traceon(`len') -@result{} -len(`123') -@error{}m4trace:2: -1- id 2: len(`123') -@result{}3 -@end example - -@item --debugfile@r{[}=@var{file}@r{]} -@itemx -o @var{file} -@itemx --error-output=@var{file} -Redirect debug messages and trace output to the -named @var{file}. Warnings, error messages, and @code{errprint} output -are still printed to standard error. Output from @code{dumpdef} goes to -this file when the debug level @code{o} is not set (@pxref{Debugmode}). -If these options are not used, or -if @var{file} is unspecified (only possible for @option{--debugfile}), -debug output goes to standard error; if @var{file} is the empty string, -debug output is discarded. @xref{Debugfile}, for more details. The -option @option{--debugfile} may be given more than once, and order is -significant with respect to file names. The spellings @option{-o} and -@option{--error-output} are misleading and -inconsistent with other GNU tools; using those spellings will -evoke a warning, and they may be withdrawn or change semantics in a -future release. - -@item -l @var{num} -@itemx --debuglen=@var{num} -@itemx --arglength=@var{num} -Restrict the size of the output generated by macro tracing or by -@code{dumpdef} to @var{num} characters per string. If unspecified or -zero, output is unlimited. @xref{Debuglen}, for more details. -@var{num} can have an optional scaling suffix. The spelling -@option{--arglength} is deprecated, since it does not match the -@code{debuglen} macro; using it will evoke a warning, and it may be -withdrawn in a future release. -@comment FIXME - Should we add an option that controls whether output -@comment strings are sanitized with escape sequences, so that dumpdef is -@comment truly one line per macro? -@comment FIXME - see comment on --nesting-limit about NUM. - -@item -t @var{name} -@itemx --trace=@var{name} -@itemx --traceon=@var{name} -This enables tracing for the macro @var{name}, at any point where it is -defined. @var{name} need not be defined when this option is given. -This option may be given more than once, and order is significant with -respect to file names. @xref{Trace}, for more details. - -@item --traceoff=@var{name} -This disables tracing for the macro @var{name}, at any point where it is -defined. @var{name} need not be defined when this option is given. -This option may be given more than once, and order is significant with -respect to file names. @xref{Trace}, for more details. -@end table - -@node Command line files -@section Specifying input files on the command line - -@cindex command line, file names on the -@cindex file names, on the command line -The remaining arguments on the command line are taken to be input file -names or module names (@pxref{Modules}). Whether or not any modules -are loaded from command line arguments, when no actual input file names -are given, then standard input is read. A file name of @file{-} can be -used to denote standard input. It is conventional, but not required, -for input file names to end in @samp{.m4} and for module names to end -in @samp{.la}. The input files and modules are attended to in the -sequence given. - -Standard input can be read more than once, so the file name @file{-} -may appear multiple times on the command line; this makes a difference -when input is from a terminal or other special file type. It is an -error if an input file ends in the middle of argument collection, a -comment, or a quoted string. -@comment FIXME - it would be nicer if we let these three things -@comment continue across file boundaries, provided that we warn in -@comment interactive use when switching to stdin in a non-default parse -@comment state. - -Various options, such as @option{--define} (@option{-D}), @option{--undefine} -(@option{-U}), @option{--synclines} (@option{-s}), @option{--trace} -(@option{-t}), and @option{--regexp-syntax} (@option{-r}), only take -effect after processing input from any file names that occur earlier -on the command line. For example, assume the file @file{foo} contains: - -@comment file: foo -@example -$ @kbd{cat foo} -bar -@end example - -The text @samp{bar} can then be redefined over multiple uses of -@file{foo}: - -@comment options: -Dbar=hello foo -Dbar=world foo -@example -$ @kbd{m4 -Dbar=hello foo -Dbar=world foo} -@result{}hello -@result{}world -@end example - -@cindex command line, module names on the -@cindex module names, on the command line -The use of loadable runtime modules in any sense is a GNU M4 -extension, so if @option{-G} is also passed or if the @env{POSIXLY_CORRECT} -environment variable is set, even otherwise valid module names will be -treated as though they were input file names (and no doubt cause havoc as -M4 tries to scan and expand the contents as if it were written in @code{m4}). - -If none of the input files invoked @code{m4exit} (@pxref{M4exit}), the -exit status of @code{m4} will be 0 for success, 1 for general failure -(such as problems with reading an input file), and 63 for version -mismatch (@pxref{Using frozen files}). - -If you need to read a file whose name starts with a @file{-}, you can -specify it as @samp{./-file}, or use @option{--} to mark the end of -options. - -@ignore -@comment Test that 'm4 file/' detects that file is not a directory; we -@comment can assume that the current directory contains a Makefile. -@comment mingw fails with EINVAL rather than ENOTDIR. - -@comment status: 1 -@comment xerr: ignore -@comment options: Makefile/ -@example -@error{}m4: cannot open file 'Makefile/': No such file or directory -@end example - -@comment Test that closed stderr does not cause a crash. Not all -@comment systems have the same message for EBADF. - -@comment xerr: ignore -@example -ifdef(`__unix__', , - `errprint(` skipping: syscmd does not have unix semantics -')m4exit(`77')')dnl -syscmd(`echo | cat >&- 2>/dev/null')ifelse(sysval, `0', - `errprint(` skipping: system does not allow closing stdout -')m4exit(`77')')dnl -changequote(`[', `]')dnl -syscmd([echo | ']__program__[' >&-])dnl -@error{}m4: write error: Bad file descriptor -sysval -@result{}1 -@end example - -@example -ifdef(`__unix__', , - `errprint(` skipping: syscmd does not have unix semantics -')m4exit(`77')')dnl -syscmd(`echo | cat >&- 2>/dev/null')ifelse(sysval, `0', - `errprint(` skipping: system does not allow closing stdout -')m4exit(`77')')dnl -changequote(`[', `]')dnl -syscmd([echo 'esyscmd(echo hi >&2 && echo err"print(bye -)d"nl)dnl' > tmp.m4 \ - && ']__program__[' tmp.m4 <&- >&- \ - && rm tmp.m4])sysval -@error{}hi -@error{}bye -@result{}0 -@end example - -@comment Test that we obey POSIX semantics with -D interspersed with -@comment files, even with POSIXLY_CORRECT (BSD getopt gets it wrong). - -$ @kbd{m4 } -@example -ifdef(`__unix__', , - `errprint(` skipping: syscmd does not have unix semantics -')m4exit(`77')')dnl -changequote(`[', `]')dnl -syscmd([POSIXLY_CORRECT=1 ']__program__[' -Dbar=hello foo -Dbar=world foo])dnl -@result{}hello -@result{}world -sysval -@result{}0 -@end example -@end ignore - -@node Syntax -@chapter Lexical and syntactic conventions - -@cindex input tokens -@cindex tokens -As @code{m4} reads its input, it separates it into @dfn{tokens}. A -token is either a name, a quoted string, or any single character, that -is not a part of either a name or a string. Input to @code{m4} can also -contain comments. GNU @code{m4} does not yet understand -multibyte locales; all operations are byte-oriented rather than -character-oriented (although if your locale uses a single byte -encoding, such as @sc{ISO-8859-1}, you will not notice a difference). -However, @code{m4} is eight-bit clean, so you can -use non-@sc{ascii} characters in quoted strings (@pxref{Changequote}), -comments (@pxref{Changecom}), and macro names (@pxref{Indir}), with the -exception of the @sc{nul} character (the zero byte @samp{'\0'}). - -@comment FIXME - each builtin needs to document how it handles NUL, then -@comment update the above paragraph to mention that NUL is now handled -@comment transparently. - -@menu -* Names:: Macro names -* Quoted strings:: Quoting input to @code{m4} -* Comments:: Comments in @code{m4} input -* Other tokens:: Other kinds of input tokens -* Input processing:: How @code{m4} copies input to output -* Regular expression syntax:: How @code{m4} interprets regular expressions -@end menu - -@node Names -@section Macro names - -@cindex names -@cindex words -A name is any sequence of letters, digits, and the character @samp{_} -(underscore), where the first character is not a digit. @code{m4} will -use the longest such sequence found in the input. If a name has a -macro definition, it will be subject to macro expansion -(@pxref{Macros}). Names are case-sensitive. - -Examples of legal names are: @samp{foo}, @samp{_tmp}, and @samp{name01}. - -The definitions of letters, digits and other input characters can be -changed at any time, using the builtin macro @code{changesyntax}. -@xref{Changesyntax}, for more information. - -@node Quoted strings -@section Quoting input to @code{m4} - -@cindex quoted string -@cindex string, quoted -A quoted string is a sequence of characters surrounded by quote -strings, defaulting to -@samp{`} (grave-accent, also known as back-tick, with UCS value U0060) -and @samp{'} (apostrophe, also known as single-quote, with UCS value -U0027), where the nested begin and end quotes within the -string are balanced. The value of a string token is the text, with one -level of quotes stripped off. Thus - -@comment ignore -@example -`' -@result{} -@end example - -@noindent -is the empty string, and double-quoting turns into single-quoting. - -@comment ignore -@example -``quoted'' -@result{}`quoted' -@end example - -The quote characters can be changed at any time, using the builtin macros -@code{changequote} (@pxref{Changequote}) or @code{changesyntax} -(@pxref{Changesyntax}). - -@node Comments -@section Comments in @code{m4} input - -@cindex comments -Comments in @code{m4} are normally delimited by the characters @samp{#} -and newline. All characters between the comment delimiters are ignored, -but the entire comment (including the delimiters) is passed through to -the output, unless you supply the @option{--discard-comments} or -@option{-c} option at the command line (@pxref{Operation modes, , -Invoking m4}). When discarding comments, the comment delimiters are -discarded, even if the close-comment string is a newline. - -Comments cannot be nested, so the first newline after a @samp{#} ends -the comment. The commenting effect of the begin-comment string -can be inhibited by quoting it. - -@example -$ @kbd{m4} -`quoted text' # `commented text' -@result{}quoted text # `commented text' -`quoting inhibits' `#' `comments' -@result{}quoting inhibits # comments -@end example - -@comment options: -c -@example -$ @kbd{m4 -c} -`quoted text' # `commented text' -`quoting inhibits' `#' `comments' -@result{}quoted text quoting inhibits # comments -@end example - -The comment delimiters can be changed to any string at any time, using -the builtin macros @code{changecom} (@pxref{Changecom}) or -@code{changesyntax} (@pxref{Changesyntax}). - -@node Other tokens -@section Other kinds of input tokens - -@cindex tokens, special -Any character, that is neither a part of a name, nor of a quoted string, -nor a comment, is a token by itself. When not in the context of macro -expansion, all of these tokens are just copied to output. However, -during macro expansion, whitespace characters (space, tab, newline, -formfeed, carriage return, vertical tab), parentheses (@samp{(} and -@samp{)}), comma (@samp{,}), and dollar (@samp{$}) have additional -roles, explained later. Which characters actually perform these roles -can be adjusted with @code{changesyntax} (@pxref{Changesyntax}). - -@node Input processing -@section How @code{m4} copies input to output - -As @code{m4} reads the input token by token, it will copy each token -directly to the output immediately. - -The exception is when it finds a word with a macro definition. In that -case @code{m4} will calculate the macro's expansion, possibly reading -more input to get the arguments. It then inserts the expansion in front -of the remaining input. In other words, the resulting text from a macro -call will be read and parsed into tokens again. - -@code{m4} expands a macro as soon as possible. If it finds a macro call -when collecting the arguments to another, it will expand the second call -first. This process continues until there are no more macro calls to -expand and all the input has been consumed. - -For a running example, examine how @code{m4} handles this input: - -@comment ignore -@example -format(`Result is %d', eval(`2**15')) -@end example - -@noindent -First, @code{m4} sees that the token @samp{format} is a macro name, so -it collects the tokens @samp{(}, @samp{`Result is %d'}, @samp{,}, -and @samp{@w{ }}, before encountering another potential macro. Sure -enough, @samp{eval} is a macro name, so the nested argument collection -picks up @samp{(}, @samp{`2**15'}, and @samp{)}, invoking the eval macro -with the lone argument of @samp{2**15}. The expansion of -@samp{eval(2**15)} is @samp{32768}, which is then rescanned as the five -tokens @samp{3}, @samp{2}, @samp{7}, @samp{6}, and @samp{8}; and -combined with the next @samp{)}, the format macro now has all its -arguments, as if the user had typed: - -@comment ignore -@example -format(`Result is %d', 32768) -@end example - -@noindent -The format macro expands to @samp{Result is 32768}, and we have another -round of scanning for the tokens @samp{Result}, @samp{@w{ }}, -@samp{is}, @samp{@w{ }}, @samp{3}, @samp{2}, @samp{7}, @samp{6}, and -@samp{8}. None of these are macros, so the final output is - -@comment ignore -@example -@result{}Result is 32768 -@end example - -As a more complicated example, we will contrast an actual code example -from the Gnulib project@footnote{Derived from a patch in -@uref{http://lists.gnu.org/archive/html/bug-gnulib/@/2007-01/@/msg00389.html}, -and a followup patch in -@uref{http://lists.gnu.org/archive/html/bug-gnulib/@/2007-02/@/msg00000.html}}, -showing both a buggy approach and the desired results. The user desires -to output a shell assignment statement that takes its argument and turns -it into a shell variable by converting it to uppercase and prepending a -prefix. The original attempt looks like this: - -@example -changequote([,])dnl -define([gl_STRING_MODULE_INDICATOR], - [ - dnl comment - GNULIB_]translit([$1],[a-z],[A-Z])[=1 - ])dnl - gl_STRING_MODULE_INDICATOR([strcase]) -@result{} @w{ } -@result{} GNULIB_strcase=1 -@result{} @w{ } -@end example - -Oops -- the argument did not get capitalized. And although the manual -is not able to easily show it, both lines that appear empty actually -contain two trailing spaces. By stepping through the parse, it is easy -to see what happened. First, @code{m4} sees the token -@samp{changequote}, which it recognizes as a macro, followed by -@samp{(}, @samp{[}, @samp{,}, @samp{]}, and @samp{)} to form the -argument list. The macro expands to the empty string, but changes the -quoting characters to something more useful for generating shell code -(unbalanced @samp{`} and @samp{'} appear all the time in shell scripts, -but unbalanced @samp{[]} tend to be rare). Also in the first line, -@code{m4} sees the token @samp{dnl}, which it recognizes as a builtin -macro that consumes the rest of the line, resulting in no output for -that line. - -The second line starts a macro definition. @code{m4} sees the token -@samp{define}, which it recognizes as a macro, followed by a @samp{(}, -@samp{[gl_STRING_MODULE_INDICATOR]}, and @samp{,}. Because an unquoted -comma was encountered, the first argument is known to be the expansion -of the single-quoted string token, or @samp{gl_STRING_MODULE_INDICATOR}. -Next, @code{m4} sees @samp{@key{NL}}, @samp{ }, and @samp{ }, but this -whitespace is discarded as part of argument collection. Then comes a -rather lengthy single-quoted string token, @samp{[@key{NL}@ @ @ @ dnl -comment@key{NL}@ @ @ @ GNULIB_]}. This is followed by the token -@samp{translit}, which @code{m4} recognizes as a macro name, so a nested -macro expansion has started. - -The arguments to the @code{translit} are found by the tokens @samp{(}, -@samp{[$1]}, @samp{,}, @samp{[a-z]}, @samp{,}, @samp{[A-Z]}, and finally -@samp{)}. All three string arguments are expanded (or in other words, -the quotes are stripped), and since neither @samp{$} nor @samp{1} need -capitalization, the result of the macro is @samp{$1}. This expansion is -rescanned, resulting in the two literal characters @samp{$} and -@samp{1}. - -Scanning of the outer macro resumes, and picks up with -@samp{[=1@key{NL}@ @ ]}, and finally @samp{)}. The collected pieces of -expanded text are concatenated, with the end result that the macro -@samp{gl_STRING_MODULE_INDICATOR} is now defined to be the sequence -@samp{@key{NL}@ @ @ @ dnl comment@key{NL}@ @ @ @ GNULIB_$1=1@key{NL}@ @ }. -Once again, @samp{dnl} is recognized and avoids a newline in the output. - -The final line is then parsed, beginning with @samp{ } and @samp{ } -that are output literally. Then @samp{gl_STRING_MODULE_INDICATOR} is -recognized as a macro name, with an argument list of @samp{(}, -@samp{[strcase]}, and @samp{)}. Since the definition of the macro -contains the sequence @samp{$1}, that sequence is replaced with the -argument @samp{strcase} prior to starting the rescan. The rescan sees -@samp{@key{NL}} and four spaces, which are output literally, then -@samp{dnl}, which discards the text @samp{ comment@key{NL}}. Next -comes four more spaces, also output literally, and the token -@samp{GNULIB_strcase}, which resulted from the earlier parameter -substitution. Since that is not a macro name, it is output literally, -followed by the literal tokens @samp{=}, @samp{1}, @samp{@key{NL}}, and -two more spaces. Finally, the original @samp{@key{NL}} seen after the -macro invocation is scanned and output literally. - -Now for a corrected approach. This rearranges the use of newlines and -whitespace so that less whitespace is output (which, although harmless -to shell scripts, can be visually unappealing), and fixes the quoting -issues so that the capitalization occurs when the macro -@samp{gl_STRING_MODULE_INDICATOR} is invoked, rather then when it is -defined. It also adds another layer of quoting to the first argument of -@code{translit}, to ensure that the output will be rescanned as a string -rather than a potential uppercase macro name needing further expansion. - -@example -changequote([,])dnl -define([gl_STRING_MODULE_INDICATOR], - [dnl comment - GNULIB_[]translit([[$1]], [a-z], [A-Z])=1dnl -])dnl - gl_STRING_MODULE_INDICATOR([strcase]) -@result{} GNULIB_STRCASE=1 -@end example - -The parsing of the first line is unchanged. The second line sees the -name of the macro to define, then sees the discarded @samp{@key{NL}} -and two spaces, as before. But this time, the next token is -@samp{[dnl comment@key{NL}@ @ GNULIB_[]translit([[$1]], [a-z], -[A-Z])=1dnl@key{NL}]}, which includes nested quotes, followed by -@samp{)} to end the macro definition and @samp{dnl} to skip the -newline. No early expansion of @code{translit} occurs, so the entire -string becomes the definition of the macro. - -The final line is then parsed, beginning with two spaces that are -output literally, and an invocation of -@code{gl_STRING_MODULE_INDICATOR} with the argument @samp{strcase}. -Again, the @samp{$1} in the macro definition is substituted prior to -rescanning. Rescanning first encounters @samp{dnl}, and discards -@samp{ comment@key{NL}}. Then two spaces are output literally. Next -comes the token @samp{GNULIB_}, but that is not a macro, so it is -output literally. The token @samp{[]} is an empty string, so it does -not affect output. Then the token @samp{translit} is encountered. - -This time, the arguments to @code{translit} are parsed as @samp{(}, -@samp{[[strcase]]}, @samp{,}, @samp{ }, @samp{[a-z]}, @samp{,}, @samp{ }, -@samp{[A-Z]}, and @samp{)}. The two spaces are discarded, and the -translit results in the desired result @samp{[STRCASE]}. This is -rescanned, but since it is a string, the quotes are stripped and the -only output is a literal @samp{STRCASE}. -Then the scanner sees @samp{=} and @samp{1}, which are output -literally, followed by @samp{dnl} which discards the rest of the -definition of @code{gl_STRING_MODULE_INDICATOR}. The newline at the -end of output is the literal @samp{@key{NL}} that appeared after the -invocation of the macro. - -The order in which @code{m4} expands the macros can be further explored -using the trace facilities of GNU @code{m4} (@pxref{Trace}). - -@node Regular expression syntax -@section How @code{m4} interprets regular expressions - -There are several contexts where @code{m4} parses an argument as a -regular expression. This section describes the various flavors of -regular expressions. @xref{Changeresyntax}. - -@include regexprops-generic.texi - -@node Macros -@chapter How to invoke macros - -This chapter covers macro invocation, macro arguments and how macro -expansion is treated. - -@menu -* Invocation:: Macro invocation -* Inhibiting Invocation:: Preventing macro invocation -* Macro Arguments:: Macro arguments -* Quoting Arguments:: On Quoting Arguments to macros -* Macro expansion:: Expanding macros -@end menu - -@node Invocation -@section Macro invocation - -@cindex macro invocation -@cindex invoking macros -Macro invocations has one of the forms - -@comment ignore -@example -name -@end example - -@noindent -which is a macro invocation without any arguments, or - -@comment ignore -@example -name(arg1, arg2, @dots{}, arg@var{n}) -@end example - -@noindent -which is a macro invocation with @var{n} arguments. Macros can have any -number of arguments. All arguments are strings, but different macros -might interpret the arguments in different ways. - -The opening parenthesis @emph{must} follow the @var{name} directly, with -no spaces in between. If it does not, the macro is called with no -arguments at all. - -For a macro call to have no arguments, the parentheses @emph{must} be -left out. The macro call - -@comment ignore -@example -name() -@end example - -@noindent -is a macro call with one argument, which is the empty string, not a call -with no arguments. - -@node Inhibiting Invocation -@section Preventing macro invocation - -An innovation of the @code{m4} language, compared to some of its -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, GNU -@code{m4} offers several mechanisms or techniques for inhibiting the -recognition of names as macro calls. - -@cindex GNU extensions -@cindex blind macro -@cindex macro, blind -First of all, many builtin macros cannot meaningfully be called without -arguments. As a GNU extension, for any of these macros, -whenever an opening parenthesis does not immediately follow their name, -the builtin macro call is not triggered. This solves the most usual -cases, like for @samp{include} or @samp{eval}. Later in this document, -the sentence ``This macro is recognized only with parameters'' refers to -this specific provision of GNU M4, also known as a blind -builtin macro. For the builtins defined by POSIX that bear -this disclaimer, POSIX specifically states that invoking those -builtins without arguments is unspecified, because many other -implementations simply invoke the builtin as though it were given one -empty argument instead. - -@example -$ @kbd{m4} -eval -@result{}eval -eval(`1') -@result{}1 -@end example - -There is also a command line option (@option{--prefix-builtins}, or -@option{-P}, @pxref{Operation modes, , Invoking m4}) that renames all -builtin macros with a prefix of @samp{m4_} at startup. The option has -no effect whatsoever on user defined macros. For example, with this option, -one has to write @code{m4_dnl} and even @code{m4_m4exit}. It also has -no effect on whether a macro requires parameters. - -@comment options: -P -@example -$ @kbd{m4 -P} -eval -@result{}eval -eval(`1') -@result{}eval(1) -m4_eval -@result{}m4_eval -m4_eval(`1') -@result{}1 -@end example - -Another alternative is to redefine problematic macros to a name less -likely to cause conflicts, using @ref{Definitions}. Or the parsing -engine can be changed to redefine what constitutes a valid macro name, -using @ref{Changesyntax}. - -Of course, the simplest way to prevent a name from being interpreted -as a call to an existing macro is to quote it. The remainder of -this section studies a little more deeply how quoting affects macro -invocation, and how quoting can be used to inhibit macro invocation. - -Even if quoting is usually done over the whole macro name, it can also -be done over only a few characters of this name (provided, of course, -that the unquoted portions are not also a macro). It is also possible -to quote the empty string, but this works only @emph{inside} the name. -For example: - -@example -`divert' -@result{}divert -`d'ivert -@result{}divert -di`ver't -@result{}divert -div`'ert -@result{}divert -@end example - -@noindent -all yield the string @samp{divert}. While in both: - -@example -`'divert -@result{} -divert`' -@result{} -@end example - -@noindent -the @code{divert} builtin macro will be called, which expands to the -empty string. - -@cindex rescanning -The output of macro evaluations is always rescanned. In the following -example, the input @samp{x`'y} yields the string @samp{bCD}, exactly as -if @code{m4} -has been given @w{@samp{substr(ab`'cde, `1', `3')}} as input: - -@example -define(`cde', `CDE') -@result{} -define(`x', `substr(ab') -@result{} -define(`y', `cde, `1', `3')') -@result{} -x`'y -@result{}bCD -@end example - -Unquoted strings on either side of a quoted string are subject to -being recognized as macro names. In the following example, quoting the -empty string allows for the second @code{macro} to be recognized as such: - -@example -define(`macro', `m') -@result{} -macro(`m')macro -@result{}mmacro -macro(`m')`'macro -@result{}mm -@end example - -Quoting may prevent recognizing as a macro name the concatenation of a -macro expansion with the surrounding characters. In this example: - -@example -define(`macro', `di$1') -@result{} -macro(`v')`ert' -@result{}divert -macro(`v')ert -@result{} -@end example - -@noindent -the input will produce the string @samp{divert}. When the quotes were -removed, the @code{divert} builtin was called instead. - -@node Macro Arguments -@section Macro arguments - -@cindex macros, arguments to -@cindex arguments to macros -When a name is seen, and it has a macro definition, it will be expanded -as a macro. - -If the name is followed by an opening parenthesis, the arguments will be -collected before the macro is called. If too few arguments are -supplied, the missing arguments are taken to be the empty string. -However, some builtins are documented to behave differently for a -missing optional argument than for an explicit empty string. If there -are too many arguments, the excess arguments are ignored. Unquoted -leading whitespace is stripped off all arguments, but whitespace -generated by a macro expansion or occurring after a macro that expanded -to an empty string remains intact. Whitespace includes space, tab, -newline, carriage return, vertical tab, and formfeed. - -@example -define(`macro', `$1') -@result{} -macro( unquoted leading space lost) -@result{}unquoted leading space lost -macro(` quoted leading space kept') -@result{} quoted leading space kept -macro( - divert `unquoted space kept after expansion') -@result{} unquoted space kept after expansion -macro(macro(` -')`whitespace from expansion kept') -@result{} -@result{}whitespace from expansion kept -macro(`unquoted trailing whitespace kept' -) -@result{}unquoted trailing whitespace kept -@result{} -@end example - -@cindex warnings, suppressing -@cindex suppressing warnings -Normally @code{m4} will issue warnings if a builtin macro is called -with an inappropriate number of arguments, but it can be suppressed with -the @option{--quiet} command line option (or @option{--silent}, or -@option{-Q}, @pxref{Operation modes, , Invoking m4}). For user -defined macros, there is no check of the number of arguments given. - -@example -$ @kbd{m4} -index(`abc') -@error{}m4:stdin:1: warning: index: too few arguments: 1 < 2 -@result{}0 -index(`abc',) -@result{}0 -index(`abc', `b', `0', `ignored') -@error{}m4:stdin:3: warning: index: extra arguments ignored: 4 > 3 -@result{}1 -@end example - -@comment options: -Q -@example -$ @kbd{m4 -Q} -index(`abc') -@result{}0 -index(`abc',) -@result{}0 -index(`abc', `b', `', `ignored') -@result{}1 -@end example - -Macros are expanded normally during argument collection, and whatever -commas, quotes and parentheses that might show up in the resulting -expanded text will serve to define the arguments as well. Thus, if -@var{foo} expands to @samp{, b, c}, the macro call - -@comment ignore -@example -bar(a foo, d) -@end example - -@noindent -is a macro call with four arguments, which are @samp{a }, @samp{b}, -@samp{c} and @samp{d}. To understand why the first argument contains -whitespace, remember that unquoted leading whitespace is never part -of an argument, but trailing whitespace always is. - -It is possible for a macro's definition to change during argument -collection, in which case the expansion uses the definition that was in -effect at the time the opening @samp{(} was seen. - -@example -define(`f', `1') -@result{} -f(define(`f', `2')) -@result{}1 -f -@result{}2 -@end example - -It is an error if the end of file occurs while collecting arguments. - -@comment status: 1 -@example -hello world -@result{}hello world -define( -^D -@error{}m4:stdin:2: define: end of file in argument list -@end example - -@node Quoting Arguments -@section On Quoting Arguments to macros - -@cindex quoted macro arguments -@cindex macros, quoted arguments to -@cindex arguments, quoted macro -Each argument has unquoted leading whitespace removed. Within each -argument, all unquoted parentheses must match. For example, if -@var{foo} is a macro, - -@comment ignore -@example -foo(() (`(') `(') -@end example - -@noindent -is a macro call, with one argument, whose value is @samp{() (() (}. -Commas separate arguments, except when they occur inside quotes, -comments, or unquoted parentheses. @xref{Pseudo Arguments}, for -examples. - -It is common practice to quote all arguments to macros, unless you are -sure you want the arguments expanded. Thus, in the above -example with the parentheses, the `right' way to do it is like this: - -@comment ignore -@example -foo(`() (() (') -@end example - -@cindex quoting rule of thumb -@cindex rule of thumb, quoting -It is, however, in certain cases necessary (because nested expansion -must occur to create the arguments for the outer macro) or convenient -(because it uses fewer characters) to leave out quotes for some -arguments, and there is nothing wrong in doing it. It just makes life a -bit harder, if you are not careful to follow a consistent quoting style. -For consistency, this manual follows the rule of thumb that each layer -of parentheses introduces another layer of single quoting, except when -showing the consequences of quoting rules. This is done even when the -quoted string cannot be a macro, such as with integers when you have not -changed the syntax via @code{changesyntax} (@pxref{Changesyntax}). - -The quoting rule of thumb of one level of quoting per parentheses has a -nice property: when a macro name appears inside parentheses, you can -determine when it will be expanded. If it is not quoted, it will be -expanded prior to the outer macro, so that its expansion becomes the -argument. If it is single-quoted, it will be expanded after the outer -macro. And if it is double-quoted, it will be used as literal text -instead of a macro name. - -@example -define(`active', `ACT, IVE') -@result{} -define(`show', `$1 $1') -@result{} -show(active) -@result{}ACT ACT -show(`active') -@result{}ACT, IVE ACT, IVE -show(``active'') -@result{}active active -@end example - -@node Macro expansion -@section Macro expansion - -@cindex macros, expansion of -@cindex expansion of macros -When the arguments, if any, to a macro call have been collected, the -macro is expanded, and the expansion text is pushed back onto the input -(unquoted), and reread. The expansion text from one macro call might -therefore result in more macros being called, if the calls are included, -completely or partially, in the first macro calls' expansion. - -Taking a very simple example, if @var{foo} expands to @samp{bar}, and -@var{bar} expands to @samp{Hello world}, the input - -@comment options: -Dbar='Hello world' -Dfoo=bar -@example -$ @kbd{m4 -Dbar="Hello world" -Dfoo=bar} -foo -@result{}Hello world -@end example - -@noindent -will expand first to @samp{bar}, and when this is reread and -expanded, into @samp{Hello world}. - -@node Definitions -@chapter How to define new macros - -@cindex macros, how to define new -@cindex defining new macros -Macros can be defined, redefined and deleted in several different ways. -Also, it is possible to redefine a macro without losing a previous -value, and bring back the original value at a later time. - -@menu -* Define:: Defining a new macro -* Arguments:: Arguments to macros -* Pseudo Arguments:: Special arguments to macros -* Undefine:: Deleting a macro -* Defn:: Renaming macros -* Pushdef:: Temporarily redefining macros -* Renamesyms:: Renaming macros with regular expressions - -* Indir:: Indirect call of macros -* Builtin:: Indirect call of builtins -* M4symbols:: Getting the defined macro names -@end menu - -@node Define -@section Defining a macro - -The normal way to define or redefine macros is to use the builtin -@code{define}: - -@deffn {Builtin (m4)} define (@var{name}, @ovar{expansion}) -Defines @var{name} to expand to @var{expansion}. If -@var{expansion} is not given, it is taken to be empty. - -The expansion of @code{define} is void. -The macro @code{define} is recognized only with parameters. -@end deffn -@comment Other implementations, such as Solaris, can define a macro -@comment with a builtin token attached to text: -@comment define(foo, a`'defn(`divnum')b) -@comment defn(`foo') => ab -@comment dumpdef(`foo') => foo: ab -@comment len(defn(`foo')) => 3 -@comment index(defn(`foo'), defn(`divnum')) => 1 -@comment foo => a0b -@comment It may be worth making some changes to support this behavior, -@comment or something similar to it. -@comment -@comment But be sure it has sane semantics, with potentially deferred -@comment expansion of builtins. For example, this should not warn -@comment about trying to access the definition of an undefined macro: -@comment define(`foo', `ifdef(`$1', 'defn(`defn')`)')foo(`oops') -@comment Also, think how to handle conflicting argument counts: -@comment define(`bar', defn(`dnl', `len')) - -The following example defines the macro @var{foo} to expand to the text -@samp{Hello World.}. - -@example -define(`foo', `Hello world.') -@result{} -foo -@result{}Hello world. -@end example - -The empty line in the output is there because the newline is not -a part of the macro definition, and it is consequently copied to -the output. This can be avoided by use of the macro @code{dnl}. -@xref{Dnl}, for details. - -The first argument to @code{define} should be quoted; otherwise, if the -macro is already defined, you will be defining a different macro. This -example shows the problems with underquoting, since we did not want to -redefine @code{one}: - -@example -define(foo, one) -@result{} -define(foo, two) -@result{} -one -@result{}two -@end example - -@cindex GNU extensions -GNU @code{m4} normally replaces only the @emph{topmost} -definition of a macro if it has several definitions from @code{pushdef} -(@pxref{Pushdef}). Some other implementations of @code{m4} replace all -definitions of a macro with @code{define}. @xref{Incompatibilities}, -for more details. - -As a GNU extension, the first argument to @code{define} does -not have to be a simple word. -It can be any text string, even the empty string. A macro with a -non-standard name cannot be invoked in the normal way, as the name is -not recognized. It can only be referenced by the builtins @code{Indir} -(@pxref{Indir}) and @code{Defn} (@pxref{Defn}). - -@cindex arrays -Arrays and associative arrays can be simulated by using non-standard -macro names. - -@deffn Composite array (@var{index}) -@deffnx Composite array_set (@var{index}, @ovar{value}) -Provide access to entries within an array. @code{array} reads the entry -at location @var{index}, and @code{array_set} assigns @var{value} to -location @var{index}. -@end deffn - -@example -define(`array', `defn(format(``array[%d]'', `$1'))') -@result{} -define(`array_set', `define(format(``array[%d]'', `$1'), `$2')') -@result{} -array_set(`4', `array element no. 4') -@result{} -array_set(`17', `array element no. 17') -@result{} -array(`4') -@result{}array element no. 4 -array(eval(`10 + 7')) -@result{}array element no. 17 -@end example - -Change the @samp{%d} to @samp{%s} and it is an associative array. - -@node Arguments -@section Arguments to macros - -@cindex macros, arguments to -@cindex arguments to macros -Macros can have arguments. The @var{n}th argument is denoted by -@code{$n} in the expansion text, and is replaced by the @var{n}th actual -argument, when the macro is expanded. Replacement of arguments happens -before rescanning, regardless of how many nesting levels of quoting -appear in the expansion. Here is an example of a macro with -two arguments. - -@deffn Composite exch (@var{arg1}, @var{arg2}) -Expands to @var{arg2} followed by @var{arg1}, effectively exchanging -their order. -@end deffn - -@example -define(`exch', `$2, $1') -@result{} -exch(`arg1', `arg2') -@result{}arg2, arg1 -@end example - -This can be used, for example, if you like the arguments to -@code{define} to be reversed. - -@example -define(`exch', `$2, $1') -@result{} -define(exch(``expansion text'', ``macro'')) -@result{} -macro -@result{}expansion text -@end example - -@xref{Quoting Arguments}, for an explanation of the double quotes. -(You should try and improve this example so that clients of @code{exch} -do not have to double quote; or @pxref{Improved exch, , Answers}). - -@cindex GNU extensions -GNU @code{m4} allows the number following the @samp{$} to -consist of one -or more digits, allowing macros to have any number of arguments. This -is not so in UNIX implementations of @code{m4}, which only recognize -one digit. -@comment FIXME - See Austin group XCU ERN 111. POSIX says that $11 must -@comment be the first argument concatenated with 1, and instead reserves -@comment ${11} for implementation use. Once this is implemented, the -@comment documentation needs to reflect how these extended arguments -@comment are handled, as well as backwards compatibility issues with -@comment 1.4.x. Also, consider adding further extensions such as -@comment ${1-default}, which expands to `default' if $1 is empty. - -As a special case, the zeroth argument, @code{$0}, is always the name -of the macro being expanded. - -@example -define(`test', ``Macro name: $0'') -@result{} -test -@result{}Macro name: test -@end example - -If you want quoted text to appear as part of the expansion text, -remember that quotes can be nested in quoted strings. Thus, in - -@example -define(`foo', `This is macro `foo'.') -@result{} -foo -@result{}This is macro foo. -@end example - -@noindent -The @samp{foo} in the expansion text is @emph{not} expanded, since it is -a quoted string, and not a name. - -@node Pseudo Arguments -@section Special arguments to macros - -@cindex special arguments to macros -@cindex macros, special arguments to -@cindex arguments to macros, special -There is a special notation for the number of actual arguments supplied, -and for all the actual arguments. - -The number of actual arguments in a macro call is denoted by @code{$#} -in the expansion text. - -@deffn Composite nargs (@dots{}) -Expands to a count of the number of arguments supplied. -@end deffn - -@example -define(`nargs', `$#') -@result{} -nargs -@result{}0 -nargs() -@result{}1 -nargs(`arg1', `arg2', `arg3') -@result{}3 -nargs(`commas can be quoted, like this') -@result{}1 -nargs(arg1#inside comments, commas do not separate arguments -still arg1) -@result{}1 -nargs((unquoted parentheses, like this, group arguments)) -@result{}1 -@end example - -Remember that @samp{#} defaults to the comment character; if you forget -quotes to inhibit the comment behavior, your macro definition may not -end where you expected. - -@example -dnl Attempt to define a macro to just `$#' -define(underquoted, $#) -oops) -@result{} -underquoted -@result{}0) -@result{}oops -@end example - -The notation @code{$*} can be used in the expansion text to denote all -the actual arguments, unquoted, with commas in between. For example - -@example -define(`echo', `$*') -@result{} -echo(arg1, arg2, arg3 , arg4) -@result{}arg1,arg2,arg3 ,arg4 -@end example - -Often each argument should be quoted, and the notation @code{$@@} handles -that. It is just like @code{$*}, except that it quotes each argument. -A simple example of that is: - -@example -define(`echo', `$@@') -@result{} -echo(arg1, arg2, arg3 , arg4) -@result{}arg1,arg2,arg3 ,arg4 -@end example - -Where did the quotes go? Of course, they were eaten, when the expanded -text were reread by @code{m4}. To show the difference, try - -@example -define(`echo1', `$*') -@result{} -define(`echo2', `$@@') -@result{} -define(`foo', `This is macro `foo'.') -@result{} -echo1(foo) -@result{}This is macro This is macro foo.. -echo1(`foo') -@result{}This is macro foo. -echo2(foo) -@result{}This is macro foo. -echo2(`foo') -@result{}foo -@end example - -@noindent -@xref{Trace}, if you do not understand this. As another example of the -difference, remember that comments encountered in arguments are passed -untouched to the macro, and that quoting disables comments. - -@example -define(`echo1', `$*') -@result{} -define(`echo2', `$@@') -@result{} -define(`foo', `bar') -@result{} -echo1(#foo'foo -foo) -@result{}#foo'foo -@result{}bar -echo2(#foo'foo -foo) -@result{}#foobar -@result{}bar' -@end example - -A @samp{$} sign in the expansion text, that is not followed by anything -@code{m4} understands, is simply copied to the macro expansion, as any -other text is. - -@example -define(`foo', `$$$ hello $$$') -@result{} -foo -@result{}$$$ hello $$$ -@end example - -@cindex rescanning -@cindex literal output -@cindex output, literal -If you want a macro to expand to something like @samp{$12}, the -judicious use of nested quoting can put a safe character between the -@code{$} and the next character, relying on the rescanning to remove the -nested quote. This will prevent @code{m4} from interpreting the -@code{$} sign as a reference to an argument. - -@example -define(`foo', `no nested quote: $1') -@result{} -foo(`arg') -@result{}no nested quote: arg -define(`foo', `nested quote around $: `$'1') -@result{} -foo(`arg') -@result{}nested quote around $: $1 -define(`foo', `nested empty quote after $: $`'1') -@result{} -foo(`arg') -@result{}nested empty quote after $: $1 -define(`foo', `nested quote around next character: $`1'') -@result{} -foo(`arg') -@result{}nested quote around next character: $1 -define(`foo', `nested quote around both: `$1'') -@result{} -foo(`arg') -@result{}nested quote around both: arg -@end example - -@node Undefine -@section Deleting a macro - -@cindex macros, how to delete -@cindex deleting macros -@cindex undefining macros -A macro definition can be removed with @code{undefine}: - -@deffn {Builtin (m4)} undefine (@var{name}@dots{}) -For each argument, remove the macro @var{name}. The macro names must -necessarily be quoted, since they will be expanded otherwise. If an -argument is not a defined macro, then the @samp{d} debug level controls -whether a warning is issued (@pxref{Debugmode}). - -The expansion of @code{undefine} is void. -The macro @code{undefine} is recognized only with parameters. -@end deffn - -@example -foo bar blah -@result{}foo bar blah -define(`foo', `some')define(`bar', `other')define(`blah', `text') -@result{} -foo bar blah -@result{}some other text -undefine(`foo') -@result{} -foo bar blah -@result{}foo other text -undefine(`bar', `blah') -@result{} -foo bar blah -@result{}foo bar blah -@end example - -Undefining a macro inside that macro's expansion is safe; the macro -still expands to the definition that was in effect at the @samp{(}. - -@example -define(`f', ``$0':$1') -@result{} -f(f(f(undefine(`f')`hello world'))) -@result{}f:f:f:hello world -f(`bye') -@result{}f(bye) -@end example - -As of M4 1.6, @code{undefine} can warn if @var{name} is not a macro, by -using @code{debugmode} (@pxref{Debugmode}) or the command line option -@option{-d} (@option{--debugmode}, @pxref{Debugging options, , Invoking -m4}). - -@example -$ @kbd{m4} -undefine(`a') -@error{}m4:stdin:1: warning: undefine: undefined macro 'a' -@result{} -debugmode(`-d') -@result{} -undefine(`a') -@result{} -@end example - -@node Defn -@section Renaming macros - -@cindex macros, how to rename -@cindex renaming macros -@cindex macros, displaying definitions -@cindex definitions, displaying macro -It is possible to rename an already defined macro. To do this, you need -the builtin @code{defn}: - -@deffn {Builtin (m4)} defn (@var{name}@dots{}) -Expands to the @emph{quoted definition} of each @var{name}. If an -argument is not a defined macro, the expansion for that argument is -empty, and the @samp{d} debug level controls whether a warning is issued -(@pxref{Debugmode}). - -If @var{name} is a user-defined macro, the quoted definition is simply -the quoted expansion text. If, instead, @var{name} is a builtin, the -expansion is a special token, which points to the builtin's internal -definition. This token meaningful primarily as the second argument to -@code{define} (and @code{pushdef}), and is silently converted to an -empty string in many other contexts. - -The macro @code{defn} is recognized only with parameters. -@end deffn - -Its normal use is best understood through an example, which shows how to -rename @code{undefine} to @code{zap}: - -@example -define(`zap', defn(`undefine')) -@result{} -zap(`undefine') -@result{} -undefine(`zap') -@result{}undefine(zap) -@end example - -In this way, @code{defn} can be used to copy macro definitions, and also -definitions of builtin macros. Even if the original macro is removed, -the other name can still be used to access the definition. - -The fact that macro definitions can be transferred also explains why you -should use @code{$0}, rather than retyping a macro's name in its -definition: - -@example -define(`foo', `This is `$0'') -@result{} -define(`bar', defn(`foo')) -@result{} -bar -@result{}This is bar -@end example - -Macros used as string variables should be referred through @code{defn}, -to avoid unwanted expansion of the text: - -@example -define(`string', `The macro dnl is very useful -') -@result{} -string -@result{}The macro@w{ } -defn(`string') -@result{}The macro dnl is very useful -@result{} -@end example - -@cindex rescanning -However, it is important to remember that @code{m4} rescanning is purely -textual. If an unbalanced end-quote string occurs in a macro -definition, the rescan will see that embedded quote as the termination -of the quoted string, and the remainder of the macro's definition will -be rescanned unquoted. Thus it is a good idea to avoid unbalanced -end-quotes in macro definitions or arguments to macros. - -@example -define(`foo', a'a) -@result{} -define(`a', `A') -@result{} -define(`echo', `$@@') -@result{} -foo -@result{}A'A -defn(`foo') -@result{}aA' -echo(foo) -@result{}AA' -@end example - -On the other hand, it is possible to exploit the fact that @code{defn} -can concatenate multiple macros prior to the rescanning phase, in order -to join the definitions of macros that, in isolation, have unbalanced -quotes. This is particularly useful when one has used several macros to -accumulate text that M4 should rescan as a whole. In the example below, -note how the use of @code{defn} on @code{l} in isolation opens a string, -which is not closed until the next line; but used on @code{l} and -@code{r} together results in nested quoting. - -@example -define(`l', `<[>')define(`r', `<]>') -@result{} -changequote(`[', `]') -@result{} -defn([l])defn([r]) -]) -@result{}<[>]defn([r]) -@result{}) -defn([l], [r]) -@result{}<[>][<]> -@end example - -@cindex builtins, special tokens -@cindex tokens, builtin macro -Using @code{defn} to generate special tokens for builtin macros will -generate a warning in contexts where a macro name is expected. But in -contexts that operate on text, the builtin token is just silently -converted to an empty string. As of M4 1.6, expansion of user macros -will also preserve builtin tokens. However, any use of builtin tokens -outside of the second argument to @code{define} and @code{pushdef} is -generally not portable, since earlier GNU M4 versions, as well -as other @code{m4} implementations, vary on how such tokens are treated. - -@example -$ @kbd{m4 -d} -defn(`defn') -@result{} -define(defn(`divnum'), `cannot redefine a builtin token') -@error{}m4:stdin:2: warning: define: invalid macro name ignored -@result{} -divnum -@result{}0 -len(defn(`divnum')) -@result{}0 -define(`echo', `$@@') -@result{} -define(`mydivnum', shift(echo(`', defn(`divnum')))) -@result{} -mydivnum -@result{}0 -define(`', `empty-$1') -@result{} -defn(defn(`divnum')) -@error{}m4:stdin:9: warning: defn: invalid macro name ignored -@result{} -pushdef(defn(`divnum'), `oops') -@error{}m4:stdin:10: warning: pushdef: invalid macro name ignored -@result{} -traceon(defn(`divnum')) -@error{}m4:stdin:11: warning: traceon: invalid macro name ignored -@result{} -indir(defn(`divnum'), `string') -@error{}m4:stdin:12: warning: indir: invalid macro name ignored -@result{} -indir(`', `string') -@result{}empty-string -traceoff(defn(`divnum')) -@error{}m4:stdin:14: warning: traceoff: invalid macro name ignored -@result{} -popdef(defn(`divnum')) -@error{}m4:stdin:15: warning: popdef: invalid macro name ignored -@result{} -dumpdef(defn(`divnum')) -@error{}m4:stdin:16: warning: dumpdef: invalid macro name ignored -@result{} -undefine(defn(`divnum')) -@error{}m4:stdin:17: warning: undefine: invalid macro name ignored -@result{} -dumpdef(`') -@error{}:@tabchar{}`empty-$1' -@result{} -m4symbols(defn(`divnum')) -@error{}m4:stdin:19: warning: m4symbols: invalid macro name ignored -@result{} -define(`foo', `define(`$1', $2)')dnl -foo(`bar', defn(`divnum')) -@result{} -bar -@result{}0 -@end example - -As of M4 1.6, @code{defn} can warn if @var{name} is not a macro, by -using @code{debugmode} (@pxref{Debugmode}) or the command line option -@option{-d} (@option{--debugmode}, @pxref{Debugging options, , Invoking -m4}). Also, @code{defn} with multiple arguments can join text with -builtin tokens. However, when defining a macro via @code{define} or -@code{pushdef}, a warning is issued and the builtin token ignored if the -builtin token does not occur in isolation. A future version of -GNU M4 may lift this restriction. - -@example -$ @kbd{m4 -d} -defn(`foo') -@error{}m4:stdin:1: warning: defn: undefined macro 'foo' -@result{} -debugmode(`-d') -@result{} -defn(`foo') -@result{} -define(`a', `A')define(`AA', `b') -@result{} -traceon(`defn', `define') -@result{} -defn(`a', `divnum', `a') -@error{}m4trace: -1- defn(`a', `divnum', `a') -> ``A'`A'' -@result{}AA -define(`mydivnum', defn(`divnum', `divnum'))mydivnum -@error{}m4trace: -2- defn(`divnum', `divnum') -> `' -@error{}m4:stdin:7: warning: define: cannot concatenate builtins -@error{}m4trace: -1- define(`mydivnum', `') -> `' -@result{} -traceoff(`defn', `define')dumpdef(`mydivnum') -@error{}mydivnum:@tabchar{}`' -@result{} -define(`mydivnum', defn(`divnum')defn(`divnum'))mydivnum -@error{}m4:stdin:9: warning: define: cannot concatenate builtins -@result{} -define(`mydivnum', defn(`divnum')`a')mydivnum -@error{}m4:stdin:10: warning: define: cannot concatenate builtins -@result{}A -define(`mydivnum', `a'defn(`divnum'))mydivnum -@error{}m4:stdin:11: warning: define: cannot concatenate builtins -@result{}A -define(`q', ``$@@'') -@result{} -define(`foo', q(`a', defn(`divnum')))foo -@error{}m4:stdin:13: warning: define: cannot concatenate builtins -@result{}a, -ifdef(`foo', `yes', `no') -@result{}yes -@end example - -@node Pushdef -@section Temporarily redefining macros - -@cindex macros, temporary redefinition of -@cindex temporary redefinition of macros -@cindex redefinition of macros, temporary -@cindex definition stack -@cindex pushdef stack -@cindex stack, macro definition -It is possible to redefine a macro temporarily, reverting to the -previous definition at a later time. This is done with the builtins -@code{pushdef} and @code{popdef}: - -@deffn {Builtin (m4)} pushdef (@var{name}, @ovar{expansion}) -@deffnx {Builtin (m4)} popdef (@var{name}@dots{}) -Analogous to @code{define} and @code{undefine}. - -These macros work in a stack-like fashion. A macro is temporarily -redefined with @code{pushdef}, which replaces an existing definition of -@var{name}, while saving the previous definition, before the new one is -installed. If there is no previous definition, @code{pushdef} behaves -exactly like @code{define}. - -If a macro has several definitions (of which only one is accessible), -the topmost definition can be removed with @code{popdef}. If there is -no previous definition, @code{popdef} behaves like @code{undefine}, and -if there is no definition at all, the @samp{d} debug level controls -whether a warning is issued (@pxref{Debugmode}). - -The expansion of both @code{pushdef} and @code{popdef} is void. -The macros @code{pushdef} and @code{popdef} are recognized only with -parameters. -@end deffn - -@example -define(`foo', `Expansion one.') -@result{} -foo -@result{}Expansion one. -pushdef(`foo', `Expansion two.') -@result{} -foo -@result{}Expansion two. -pushdef(`foo', `Expansion three.') -@result{} -pushdef(`foo', `Expansion four.') -@result{} -popdef(`foo') -@result{} -foo -@result{}Expansion three. -popdef(`foo', `foo') -@result{} -foo -@result{}Expansion one. -popdef(`foo') -@result{} -foo -@result{}foo -@end example - -If a macro with several definitions is redefined with @code{define}, the -topmost definition is @emph{replaced} with the new definition. If it is -removed with @code{undefine}, @emph{all} the definitions are removed, -and not only the topmost one. However, POSIX allows other -implementations that treat @code{define} as replacing an entire stack -of definitions with a single new definition, so to be portable to other -implementations, it may be worth explicitly using @code{popdef} and -@code{pushdef} rather than relying on the GNU behavior of -@code{define}. - -@example -define(`foo', `Expansion one.') -@result{} -foo -@result{}Expansion one. -pushdef(`foo', `Expansion two.') -@result{} -foo -@result{}Expansion two. -define(`foo', `Second expansion two.') -@result{} -foo -@result{}Second expansion two. -undefine(`foo') -@result{} -foo -@result{}foo -@end example - -@cindex local variables -@cindex variables, local -Local variables within macros are made with @code{pushdef} and -@code{popdef}. At the start of the macro a new definition is pushed, -within the macro it is manipulated and at the end it is popped, -revealing the former definition. - -It is possible to temporarily redefine a builtin with @code{pushdef} -and @code{defn}. - -As of M4 1.6, @code{popdef} can warn if @var{name} is not a macro, by -using @code{debugmode} (@pxref{Debugmode}) or the command line option -@option{-d} (@option{--debugmode}, @pxref{Debugging options, , Invoking -m4}). - -@example -define(`a', `1') -@result{} -popdef -@result{}popdef -popdef(`a', `a') -@error{}m4:stdin:3: warning: popdef: undefined macro 'a' -@result{} -debugmode(`-d') -@result{} -popdef(`a') -@result{} -@end example - -@node Renamesyms -@section Renaming macros with regular expressions - -@cindex regular expressions -@cindex macros, how to rename -@cindex renaming macros -@cindex GNU extensions -Sometimes it is desirable to rename multiple symbols without having to -use a long sequence of calls to @code{define}. The @code{renamesyms} -builtin allows this: - -@deffn {Builtin (gnu)} renamesyms (@var{regexp}, @var{replacement}, @ - @ovar{resyntax}) -Global renaming of macros is done by @code{renamesyms}, which selects -all macros with names that match @var{regexp}, and renames each match -according to @var{replacement}. It is unspecified what happens if the -rename causes multiple macros to map to the same name. -@comment FIXME - right now, collisions cause a core dump on some platforms: -@comment define(bar,1)define(baz,2)renamesyms(^ba., baa)dumpdef(`baa') - -If @var{resyntax} is given, the particular flavor of regular -expression understood with respect to @var{regexp} can be changed from -the current default. @xref{Changeresyntax}, for details of the values -that can be given for this argument. - -A macro that does not have a name that matches @var{regexp} is left -with its original name. If only part of the name matches, any part of -the name that is not covered by @var{regexp} is copied to the -replacement name. Whenever a match is found in the name, the search -proceeds from the end of the match, so no character in the original -name can be substituted twice. If @var{regexp} matches a string of -zero length, the start position for the continued search is -incremented to avoid infinite loops. - -Where a replacement is to be made, @var{replacement} replaces the -matched text in the original name, with @samp{\@var{n}} substituted by -the text matched by the @var{n}th parenthesized sub-expression of -@var{regexp}, and @samp{\&} being the text matched by the entire -regular expression. - -The expansion of @code{renamesyms} is void. -The macro @code{renamesyms} is recognized only with parameters. -This macro was added in M4 2.0. -@end deffn - -The following example starts with a rename similar to the -@option{--prefix-builtins} option (or @option{-P}), prefixing every -macro with @code{m4_}. However, note that @option{-P} only renames M4 -builtin macros, even if other macros were defined previously, while -@code{renamesyms} will rename any macros that match when it runs, -including text macros. The rest of the example demonstrates the -behavior of unanchored regular expressions in symbol renaming. - -@comment options: -Dfoo=bar -P -@example -$ @kbd{m4 -Dfoo=bar -P} -foo -@result{}bar -m4_foo -@result{}m4_foo -m4_defn(`foo') -@result{}bar -@end example - -@example -$ @kbd{m4} -define(`foo', `bar') -@result{} -renamesyms(`^.*$', `m4_\&') -@result{} -foo -@result{}foo -m4_foo -@result{}bar -m4_defn(`m4_foo') -@result{}bar -m4_renamesyms(`f', `g') -@result{} -m4_igdeg(`m4_goo', `m4_goo') -@result{}bar -@end example - -If @var{resyntax} is given, @var{regexp} must be given according to -the syntax chosen, though the default regular expression syntax -remains unchanged for other invocations. Here is a more realistic -example that performs a similar renaming on macros, except that it -ignores macros with names that begin with @samp{_}, and avoids creating -macros with names that begin with @samp{m4_m4}. - -@example -renamesyms(`^[^_]\w*$', `m4_\&') -@result{} -m4_renamesyms(`^m4_m4(\w*)$', `m4_\1', `POSIX_EXTENDED') -@result{} -m4_wrap(__line__ -) -@result{} -^D -@result{}3 -@end example - -When a symbol has multiple definitions, thanks to @code{pushdef}, the -entire stack is renamed. - -@example -pushdef(`foo', `1')pushdef(`foo', `2') -@result{} -renamesyms(`^foo$', `bar') -@result{} -bar -@result{}2 -popdef(`bar')bar -@result{}1 -popdef(`bar')bar -@result{}bar -@end example - -@node Indir -@section Indirect call of macros - -@cindex indirect call of macros -@cindex call of macros, indirect -@cindex macros, indirect call of -@cindex GNU extensions -Any macro can be called indirectly with @code{indir}: - -@deffn {Builtin (gnu)} indir (@var{name}, @ovar{args@dots{}}) -Results in a call to the macro @var{name}, which is passed the rest of -the arguments @var{args}. If @var{name} is not defined, the expansion -is void, and the @samp{d} debug level controls whether a warning is -issued (@pxref{Debugmode}). - -The macro @code{indir} is recognized only with parameters. -@end deffn - -This can be used to call macros with computed or ``invalid'' -names (@code{define} allows such names to be defined): - -@example -define(`$$internal$macro', `Internal macro (name `$0')') -@result{} -$$internal$macro -@result{}$$internal$macro -indir(`$$internal$macro') -@result{}Internal macro (name $$internal$macro) -@end example - -The point is, here, that larger macro packages can have private macros -defined, that will not be called by accident. They can @emph{only} be -called through the builtin @code{indir}. - -One other point to observe is that argument collection occurs before -@code{indir} invokes @var{name}, so if argument collection changes the -value of @var{name}, that will be reflected in the final expansion. -This is different than the behavior when invoking macros directly, -where the definition that was in effect before argument collection is -used. - -@example -$ @kbd{m4 -d} -define(`f', `1') -@result{} -f(define(`f', `2')) -@result{}1 -indir(`f', define(`f', `3')) -@result{}3 -indir(`f', undefine(`f')) -@error{}m4:stdin:4: warning: indir: undefined macro 'f' -@result{} -debugmode(`-d') -@result{} -indir(`f') -@result{} -@end example - -When handed the result of @code{defn} (@pxref{Defn}) as one of its -arguments, @code{indir} defers to the invoked @var{name} for whether a -token representing a builtin is recognized or flattened to the empty -string. - -@example -$ @kbd{m4 -d} -indir(defn(`defn'), `divnum') -@error{}m4:stdin:1: warning: indir: invalid macro name ignored -@result{} -indir(`define', defn(`defn'), `divnum') -@error{}m4:stdin:2: warning: define: invalid macro name ignored -@result{} -indir(`define', `foo', defn(`divnum')) -@result{} -foo -@result{}0 -indir(`divert', defn(`foo')) -@error{}m4:stdin:5: warning: divert: empty string treated as 0 -@result{} -@end example - -Warning messages issued on behalf of an indirect macro use an -unambiguous representation of the macro name, using escape sequences -similar to C strings, and with colons also quoted. - -@example -define(`%%:\ -odd', defn(`divnum')) -@result{} -indir(`%%:\ -odd', `extra') -@error{}m4:stdin:3: warning: %%\:\\\nodd: extra arguments ignored: 1 > 0 -@result{}0 -@end example - -@node Builtin -@section Indirect call of builtins - -@cindex indirect call of builtins -@cindex call of builtins, indirect -@cindex builtins, indirect call of -@cindex GNU extensions -Builtin macros can be called indirectly with @code{builtin}: - -@deffn {Builtin (gnu)} builtin (@var{name}, @ovar{args@dots{}}) -@deffnx {Builtin (gnu)} builtin (@code{defn(`builtin')}, @var{name1}) -Results in a call to the builtin @var{name}, which is passed the -rest of the arguments @var{args}. If @var{name} does not name a -builtin, the expansion is void, and the @samp{d} debug level controls -whether a warning is issued (@pxref{Debugmode}). - -As a special case, if @var{name} is exactly the special token -representing the @code{builtin} macro, as obtained by @code{defn} -(@pxref{Defn}), then @var{args} must consist of a single @var{name1}, -and the expansion is the special token representing the builtin macro -named by @var{name1}. - -The macro @code{builtin} is recognized only with parameters. -@end deffn - -This can be used even if @var{name} has been given another definition -that has covered the original, or been undefined so that no macro -maps to the builtin. - -@example -pushdef(`define', `hidden') -@result{} -undefine(`undefine') -@result{} -define(`foo', `bar') -@result{}hidden -foo -@result{}foo -builtin(`define', `foo', defn(`divnum')) -@result{} -foo -@result{}0 -builtin(`define', `foo', `BAR') -@result{} -foo -@result{}BAR -undefine(`foo') -@result{}undefine(foo) -foo -@result{}BAR -builtin(`undefine', `foo') -@result{} -foo -@result{}foo -@end example - -The @var{name} argument only matches the original name of the builtin, -even when the @option{--prefix-builtins} option (or @option{-P}, -@pxref{Operation modes, , Invoking m4}) is in effect. This is different -from @code{indir}, which only tracks current macro names. - -@comment options: -P -@example -$ @kbd{m4 -P} -m4_builtin(`divnum') -@result{}0 -m4_builtin(`m4_divnum') -@error{}m4:stdin:2: warning: m4_builtin: undefined builtin 'm4_divnum' -@result{} -m4_indir(`divnum') -@error{}m4:stdin:3: warning: m4_indir: undefined macro 'divnum' -@result{} -m4_indir(`m4_divnum') -@result{}0 -m4_debugmode(`-d') -@result{} -m4_builtin(`m4_divnum') -@result{} -@end example - -Note that @code{indir} and @code{builtin} can be used to invoke builtins -without arguments, even when they normally require parameters to be -recognized; but it will provoke a warning, and the expansion will behave -as though empty strings had been passed as the required arguments. - -@example -builtin -@result{}builtin -builtin() -@error{}m4:stdin:2: warning: builtin: undefined builtin '' -@result{} -builtin(`builtin') -@error{}m4:stdin:3: warning: builtin: too few arguments: 0 < 1 -@result{} -builtin(`builtin',) -@error{}m4:stdin:4: warning: builtin: undefined builtin '' -@result{} -builtin(`builtin', ``' -') -@error{}m4:stdin:5: warning: builtin: undefined builtin '`\'\n' -@result{} -indir(`index') -@error{}m4:stdin:7: warning: index: too few arguments: 0 < 2 -@result{}0 -@end example - -Normally, once a builtin macro is undefined, the only way to retrieve -its functionality is by defining a new macro that expands to -@code{builtin} under the hood. But this extra layer of expansion is -slightly inefficient, not to mention the fact that it is not robust to -changes in the current quoting scheme due to @code{changequote} -(@pxref{Changequote}). On the other hand, defining a macro to the -special token produced by @code{defn} (@pxref{Defn}) is very efficient, -and avoids the need for quoting within the macro definition; but -@code{defn} only works if the desired macro is already defined by some -other name. So @code{builtin} provides a special case where it is -possible to retrieve the same special token representing a builtin as -what @code{defn} would provide, were the desired macro still defined. -This feature is activated by passing @code{defn(`builtin')} as the first -argument to builtin. Normally, passing a special token representing a -macro as @var{name} results in a warning and an empty expansion, but in -this case, if the second argument @var{name1} names a valid builtin, -there is no warning and the expansion is the appropriate special -token. In fact, with just the @code{builtin} macro accessible, it is -possible to reconstitute the entire startup state of @code{m4}. - -In the example below, compare the number of macro invocations performed -by @code{defn1} and @code{defn2}, and the differences once quoting is -changed. - -@example -$ @kbd{m4 -d} -undefine(`defn') -@result{} -define(`foo', `bar') -@result{} -define(`defn1', `builtin(`defn', $@@)') -@result{} -define(`defn2', builtin(builtin(`defn', `builtin'), `defn')) -@result{} -dumpdef(`defn1', `defn2') -@error{}defn1:@tabchar{}`builtin(`defn', $@@)' -@error{}defn2:@tabchar{} -@result{} -traceon -@result{} -defn1(`foo') -@error{}m4trace: -1- defn1(`foo') -> `builtin(`defn', `foo')' -@error{}m4trace: -1- builtin(`defn', `foo') -> ``bar'' -@result{}bar -defn2(`foo') -@error{}m4trace: -1- defn2(`foo') -> ``bar'' -@result{}bar -traceoff -@error{}m4trace: -1- traceoff -> `' -@result{} -changequote(`[', `]') -@result{} -defn1([foo]) -@error{}m4:stdin:11: warning: builtin: undefined builtin '`defn\'' -@result{} -defn2([foo]) -@result{}bar -define([defn1], [builtin([defn], $@@)]) -@result{} -defn1([foo]) -@result{}bar -changequote -@result{} -defn1(`foo') -@error{}m4:stdin:16: warning: builtin: undefined builtin '[defn]' -@result{} -@end example - -@node M4symbols -@section Getting the defined macro names - -@cindex macro names, listing -@cindex listing macro names -@cindex currently defined macros -@cindex GNU extensions -The name of the currently defined macros can be accessed by -@code{m4symbols}: - -@deffn {Builtin (gnu)} m4symbols (@ovar{names@dots{}}) -Without arguments, @code{m4symbols} expands to a sorted list of quoted -strings, separated by commas. This contrasts with @code{dumpdef} -(@pxref{Dumpdef}), whose output cannot be accessed by @code{m4} -programs. - -When given arguments, @code{m4symbols} returns the sorted subset of the -@var{names} currently defined, and silently ignores the rest. -This macro was added in M4 2.0. -@end deffn - -@example -m4symbols(`ifndef', `ifdef', `define', `undef') -@result{}define,ifdef -@end example - -@node Conditionals -@chapter Conditionals, loops, and recursion - -Macros, expanding to plain text, perhaps with arguments, are not quite -enough. We would like to have macros expand to different things, based -on decisions taken at run-time. For that, we need some kind of conditionals. -Also, we would like to have some kind of loop construct, so we could do -something a number of times, or while some condition is true. - -@menu -* Ifdef:: Testing if a macro is defined -* Ifelse:: If-else construct, or multibranch -* Shift:: Recursion in @code{m4} -* Forloop:: Iteration by counting -* Foreach:: Iteration by list contents -* Stacks:: Working with definition stacks -* Composition:: Building macros with macros -@end menu - -@node Ifdef -@section Testing if a macro is defined - -@cindex conditionals -There are two different builtin conditionals in @code{m4}. The first is -@code{ifdef}: - -@deffn {Builtin (m4)} ifdef (@var{name}, @var{string-1}, @ovar{string-2}) -If @var{name} is defined as a macro, @code{ifdef} expands to -@var{string-1}, otherwise to @var{string-2}. If @var{string-2} is -omitted, it is taken to be the empty string (according to the normal -rules). - -The macro @code{ifdef} is recognized only with parameters. -@end deffn - -@example -ifdef(`foo', ``foo' is defined', ``foo' is not defined') -@result{}foo is not defined -define(`foo', `') -@result{} -ifdef(`foo', ``foo' is defined', ``foo' is not defined') -@result{}foo is defined -ifdef(`no_such_macro', `yes', `no', `extra argument') -@error{}m4:stdin:4: warning: ifdef: extra arguments ignored: 4 > 3 -@result{}no -@end example - -As of M4 1.6, @code{ifdef} transparently handles builtin tokens -generated by @code{defn} (@pxref{Defn}) that occur in either -@var{string}, although a warning is issued for invalid macro names. - -@example -define(`', `empty') -@result{} -ifdef(defn(`defn'), `yes', `no') -@error{}m4:stdin:2: warning: ifdef: invalid macro name ignored -@result{}no -define(`foo', ifdef(`divnum', defn(`divnum'), `undefined')) -@result{} -foo -@result{}0 -@end example - -@node Ifelse -@section If-else construct, or multibranch - -@cindex comparing strings -@cindex discarding input -@cindex input, discarding -The other conditional, @code{ifelse}, is much more powerful. It can be -used as a way to introduce a long comment, as an if-else construct, or -as a multibranch, depending on the number of arguments supplied: - -@deffn {Builtin (m4)} ifelse (@var{comment}) -@deffnx {Builtin (m4)} ifelse (@var{string-1}, @var{string-2}, @var{equal}, @ - @ovar{not-equal}) -@deffnx {Builtin (m4)} ifelse (@var{string-1}, @var{string-2}, @var{equal-1}, @ - @var{string-3}, @var{string-4}, @var{equal-2}, @dots{}, @ovar{not-equal}) -Used with only one argument, the @code{ifelse} simply discards it and -produces no output. - -If called with three or four arguments, @code{ifelse} expands into -@var{equal}, if @var{string-1} and @var{string-2} are equal (character -for character), otherwise it expands to @var{not-equal}. A final fifth -argument is ignored, after triggering a warning. - -If called with six or more arguments, and @var{string-1} and -@var{string-2} are equal, @code{ifelse} expands into @var{equal-1}, -otherwise the first three arguments are discarded and the processing -starts again. - -The macro @code{ifelse} is recognized only with parameters. -@end deffn - -Using only one argument is a common @code{m4} idiom for introducing a -block comment, as an alternative to repeatedly using @code{dnl}. This -special usage is recognized by GNU @code{m4}, so that in this -case, the warning about missing arguments is never triggered. - -@example -ifelse(`some comments') -@result{} -ifelse(`foo', `bar') -@error{}m4:stdin:2: warning: ifelse: too few arguments: 2 < 3 -@result{} -@end example - -Using three or four arguments provides decision points. - -@example -ifelse(`foo', `bar', `true') -@result{} -ifelse(`foo', `foo', `true') -@result{}true -define(`foo', `bar') -@result{} -ifelse(foo, `bar', `true', `false') -@result{}true -ifelse(foo, `foo', `true', `false') -@result{}false -@end example - -@cindex macro, blind -@cindex blind macro -Notice how the first argument was used unquoted; it is common to compare -the expansion of a macro with a string. With this macro, you can now -reproduce the behavior of blind builtins, where the macro is recognized -only with arguments. - -@example -define(`foo', `ifelse(`$#', `0', ``$0'', `arguments:$#')') -@result{} -foo -@result{}foo -foo() -@result{}arguments:1 -foo(`a', `b', `c') -@result{}arguments:3 -@end example - -For an example of a way to make defining blind macros easier, see -@ref{Composition}. - -@cindex multibranches -@cindex switch statement -@cindex case statement -The macro @code{ifelse} can take more than four arguments. If given more -than four arguments, @code{ifelse} works like a @code{case} or @code{switch} -statement in traditional programming languages. If @var{string-1} and -@var{string-2} are equal, @code{ifelse} expands into @var{equal-1}, otherwise -the procedure is repeated with the first three arguments discarded. This -calls for an example: - -@example -ifelse(`foo', `bar', `third', `gnu', `gnats') -@error{}m4:stdin:1: warning: ifelse: extra arguments ignored: 5 > 4 -@result{}gnu -ifelse(`foo', `bar', `third', `gnu', `gnats', `sixth') -@result{} -ifelse(`foo', `bar', `third', `gnu', `gnats', `sixth', `seventh') -@result{}seventh -ifelse(`foo', `bar', `3', `gnu', `gnats', `6', `7', `8') -@error{}m4:stdin:4: warning: ifelse: extra arguments ignored: 8 > 7 -@result{}7 -@end example - -As of M4 1.6, @code{ifelse} transparently handles builtin tokens -generated by @code{defn} (@pxref{Defn}). Because of this, it is always -safe to compare two macro definitions, without worrying whether the -macro might be a builtin. - -@example -ifelse(defn(`defn'), `', `yes', `no') -@result{}no -ifelse(defn(`defn'), defn(`divnum'), `yes', `no') -@result{}no -ifelse(defn(`defn'), defn(`defn'), `yes', `no') -@result{}yes -define(`foo', ifelse(`', `', defn(`divnum'))) -@result{} -foo -@result{}0 -@end example - -Naturally, the normal case will be slightly more advanced than these -examples. A common use of @code{ifelse} is in macros implementing loops -of various kinds. - -@node Shift -@section Recursion in @code{m4} - -@cindex recursive macros -@cindex macros, recursive -There is no direct support for loops in @code{m4}, but macros can be -recursive. There is no limit on the number of recursion levels, other -than those enforced by your hardware and operating system. - -@cindex loops -Loops can be programmed using recursion and the conditionals described -previously. - -There is a builtin macro, @code{shift}, which can, among other things, -be used for iterating through the actual arguments to a macro: - -@deffn {Builtin (m4)} shift (@var{arg1}, @dots{}) -Takes any number of arguments, and expands to all its arguments except -@var{arg1}, separated by commas, with each argument quoted. - -The macro @code{shift} is recognized only with parameters. -@end deffn - -@example -shift -@result{}shift -shift(`bar') -@result{} -shift(`foo', `bar', `baz') -@result{}bar,baz -@end example - -An example of the use of @code{shift} is this macro: - -@cindex reversing arguments -@cindex arguments, reversing -@deffn Composite reverse (@dots{}) -Takes any number of arguments, and reverses their order. -@end deffn - -It is implemented as: - -@example -define(`reverse', `ifelse(`$#', `0', , `$#', `1', ``$1'', - `reverse(shift($@@)), `$1'')') -@result{} -reverse -@result{} -reverse(`foo') -@result{}foo -reverse(`foo', `bar', `gnats', `and gnus') -@result{}and gnus, gnats, bar, foo -@end example - -While not a very interesting macro, it does show how simple loops can be -made with @code{shift}, @code{ifelse} and recursion. It also shows -that @code{shift} is usually used with @samp{$@@}. Another example of -this is an implementation of a short-circuiting conditional operator. - -@cindex short-circuiting conditional -@cindex conditional, short-circuiting -@deffn Composite cond (@var{test-1}, @var{string-1}, @var{equal-1}, @ - @ovar{test-2}, @ovar{string-2}, @ovar{equal-2}, @dots{}, @ovar{not-equal}) -Similar to @code{ifelse}, where an equal comparison between the first -two strings results in the third, otherwise the first three arguments -are discarded and the process repeats. The difference is that each -@var{test-} is expanded only when it is encountered. This means that -every third argument to @code{cond} is normally given one more level of -quoting than the corresponding argument to @code{ifelse}. -@end deffn - -Here is the implementation of @code{cond}, along with a demonstration of -how it can short-circuit the side effects in @code{side}. Notice how -all the unquoted side effects happen regardless of how many comparisons -are made with @code{ifelse}, compared with only the relevant effects -with @code{cond}. - -@example -define(`cond', -`ifelse(`$#', `1', `$1', - `ifelse($1, `$2', `$3', - `$0(shift(shift(shift($@@))))')')')dnl -define(`side', `define(`counter', incr(counter))$1')dnl -define(`example1', -`define(`counter', `0')dnl -ifelse(side(`$1'), `yes', `one comparison: ', - side(`$1'), `no', `two comparisons: ', - side(`$1'), `maybe', `three comparisons: ', - `side(`default answer: ')')counter')dnl -define(`example2', -`define(`counter', `0')dnl -cond(`side(`$1')', `yes', `one comparison: ', - `side(`$1')', `no', `two comparisons: ', - `side(`$1')', `maybe', `three comparisons: ', - `side(`default answer: ')')counter')dnl -example1(`yes') -@result{}one comparison: 3 -example1(`no') -@result{}two comparisons: 3 -example1(`maybe') -@result{}three comparisons: 3 -example1(`feeling rather indecisive today') -@result{}default answer: 4 -example2(`yes') -@result{}one comparison: 1 -example2(`no') -@result{}two comparisons: 2 -example2(`maybe') -@result{}three comparisons: 3 -example2(`feeling rather indecisive today') -@result{}default answer: 4 -@end example - -@cindex joining arguments -@cindex arguments, joining -@cindex concatenating arguments -Another common task that requires iteration is joining a list of -arguments into a single string. - -@deffn Composite join (@ovar{separator}, @ovar{args@dots{}}) -@deffnx Composite joinall (@ovar{separator}, @ovar{args@dots{}}) -Generate a single-quoted string, consisting of each @var{arg} separated -by @var{separator}. While @code{joinall} always outputs a -@var{separator} between arguments, @code{join} avoids the -@var{separator} for an empty @var{arg}. -@end deffn - -Here are some examples of its usage, based on the implementation -@file{m4-@value{VERSION}/@/doc/examples/@/join.m4} distributed in this -package: - -@comment examples -@example -$ @kbd{m4 -I examples} -include(`join.m4') -@result{} -join,join(`-'),join(`-', `'),join(`-', `', `') -@result{},,, -joinall,joinall(`-'),joinall(`-', `'),joinall(`-', `', `') -@result{},,,- -join(`-', `1') -@result{}1 -join(`-', `1', `2', `3') -@result{}1-2-3 -join(`', `1', `2', `3') -@result{}123 -join(`-', `', `1', `', `', `2', `') -@result{}1-2 -joinall(`-', `', `1', `', `', `2', `') -@result{}-1---2- -join(`,', `1', `2', `3') -@result{}1,2,3 -define(`nargs', `$#')dnl -nargs(join(`,', `1', `2', `3')) -@result{}1 -@end example - -Examining the implementation shows some interesting points about several -m4 programming idioms. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -undivert(`join.m4')dnl -@result{}divert(`-1') -@result{}# join(sep, args) - join each non-empty ARG into a single -@result{}# string, with each element separated by SEP -@result{}define(`join', -@result{}`ifelse(`$#', `2', ``$2'', -@result{} `ifelse(`$2', `', `', ``$2'_')$0(`$1', shift(shift($@@)))')') -@result{}define(`_join', -@result{}`ifelse(`$#$2', `2', `', -@result{} `ifelse(`$2', `', `', ``$1$2'')$0(`$1', shift(shift($@@)))')') -@result{}# joinall(sep, args) - join each ARG, including empty ones, -@result{}# into a single string, with each element separated by SEP -@result{}define(`joinall', ``$2'_$0(`$1', shift($@@))') -@result{}define(`_joinall', -@result{}`ifelse(`$#', `2', `', ``$1$3'$0(`$1', shift(shift($@@)))')') -@result{}divert`'dnl -@end example - -First, notice that this implementation creates helper macros -@code{_join} and @code{_joinall}. This division of labor makes it -easier to output the correct number of @var{separator} instances: -@code{join} and @code{joinall} are responsible for the first argument, -without a separator, while @code{_join} and @code{_joinall} are -responsible for all remaining arguments, always outputting a separator -when outputting an argument. - -Next, observe how @code{join} decides to iterate to itself, because the -first @var{arg} was empty, or to output the argument and swap over to -@code{_join}. If the argument is non-empty, then the nested -@code{ifelse} results in an unquoted @samp{_}, which is concatenated -with the @samp{$0} to form the next macro name to invoke. The -@code{joinall} implementation is simpler since it does not have to -suppress empty @var{arg}; it always executes once then defers to -@code{_joinall}. - -Another important idiom is the idea that @var{separator} is reused for -each iteration. Each iteration has one less argument, but rather than -discarding @samp{$1} by iterating with @code{$0(shift($@@))}, the macro -discards @samp{$2} by using @code{$0(`$1', shift(shift($@@)))}. - -Next, notice that it is possible to compare more than one condition in a -single @code{ifelse} test. The test of @samp{$#$2} against @samp{2} -allows @code{_join} to iterate for two separate reasons---either there -are still more than two arguments, or there are exactly two arguments -but the last argument is not empty. - -Finally, notice that these macros require exactly two arguments to -terminate recursion, but that they still correctly result in empty -output when given no @var{args} (i.e., zero or one macro argument). On -the first pass when there are too few arguments, the @code{shift} -results in no output, but leaves an empty string to serve as the -required second argument for the second pass. Put another way, -@samp{`$1', shift($@@)} is not the same as @samp{$@@}, since only the -former guarantees at least two arguments. - -@cindex quote manipulation -@cindex manipulating quotes -Sometimes, a recursive algorithm requires adding quotes to each element, -or treating multiple arguments as a single element: - -@deffn Composite quote (@dots{}) -@deffnx Composite dquote (@dots{}) -@deffnx Composite dquote_elt (@dots{}) -Takes any number of arguments, and adds quoting. With @code{quote}, -only one level of quoting is added, effectively removing whitespace -after commas and turning multiple arguments into a single string. With -@code{dquote}, two levels of quoting are added, one around each element, -and one around the list. And with @code{dquote_elt}, two levels of -quoting are added around each element. -@end deffn - -An actual implementation of these three macros is distributed as -@file{m4-@value{VERSION}/@/doc/examples/@/quote.m4} in this package. -First, let's examine their usage: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`quote.m4') -@result{} --quote-dquote-dquote_elt- -@result{}---- --quote()-dquote()-dquote_elt()- -@result{}--`'-`'- --quote(`1')-dquote(`1')-dquote_elt(`1')- -@result{}-1-`1'-`1'- --quote(`1', `2')-dquote(`1', `2')-dquote_elt(`1', `2')- -@result{}-1,2-`1',`2'-`1',`2'- -define(`n', `$#')dnl --n(quote(`1', `2'))-n(dquote(`1', `2'))-n(dquote_elt(`1', `2'))- -@result{}-1-1-2- -dquote(dquote_elt(`1', `2')) -@result{}``1'',``2'' -dquote_elt(dquote(`1', `2')) -@result{}``1',`2'' -@end example - -The last two lines show that when given two arguments, @code{dquote} -results in one string, while @code{dquote_elt} results in two. Now, -examine the implementation. Note that @code{quote} and -@code{dquote_elt} make decisions based on their number of arguments, so -that when called without arguments, they result in nothing instead of a -quoted empty string; this is so that it is possible to distinguish -between no arguments and an empty first argument. @code{dquote}, on the -other hand, results in a string no matter what, since it is still -possible to tell whether it was invoked without arguments based on the -resulting string. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -undivert(`quote.m4')dnl -@result{}divert(`-1') -@result{}# quote(args) - convert args to single-quoted string -@result{}define(`quote', `ifelse(`$#', `0', `', ``$*'')') -@result{}# dquote(args) - convert args to quoted list of quoted strings -@result{}define(`dquote', ``$@@'') -@result{}# dquote_elt(args) - convert args to list of double-quoted strings -@result{}define(`dquote_elt', `ifelse(`$#', `0', `', `$#', `1', ```$1''', -@result{} ```$1'',$0(shift($@@))')') -@result{}divert`'dnl -@end example - -It is worth pointing out that @samp{quote(@var{args})} is more efficient -than @samp{joinall(`,', @var{args})} for producing the same output. - -@cindex nine arguments, more than -@cindex more than nine arguments -@cindex arguments, more than nine -One more useful macro based on @code{shift} allows portably selecting -an arbitrary argument (usually greater than the ninth argument), without -relying on the GNU extension of multi-digit arguments -(@pxref{Arguments}). - -@deffn Composite argn (@var{n}, @dots{}) -Expands to argument @var{n} out of the remaining arguments. @var{n} -must be a positive number. Usually invoked as -@samp{argn(`@var{n}',$@@)}. -@end deffn - -It is implemented as: - -@example -define(`argn', `ifelse(`$1', 1, ``$2'', - `argn(decr(`$1'), shift(shift($@@)))')') -@result{} -argn(`1', `a') -@result{}a -define(`foo', `argn(`11', $@@)') -@result{} -foo(`a', `b', `c', `d', `e', `f', `g', `h', `i', `j', `k', `l') -@result{}k -@end example - -@node Forloop -@section Iteration by counting - -@cindex for loops -@cindex loops, counting -@cindex counting loops -Here is an example of a loop macro that implements a simple for loop. - -@deffn Composite forloop (@var{iterator}, @var{start}, @var{end}, @var{text}) -Takes the name in @var{iterator}, which must be a valid macro name, and -successively assign it each integer value from @var{start} to @var{end}, -inclusive. For each assignment to @var{iterator}, append @var{text} to -the expansion of the @code{forloop}. @var{text} may refer to -@var{iterator}. Any definition of @var{iterator} prior to this -invocation is restored. -@end deffn - -It can, for example, be used for simple counting: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`forloop.m4') -@result{} -forloop(`i', `1', `8', `i ') -@result{}1 2 3 4 5 6 7 8@w{ } -@end example - -For-loops can be nested, like: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`forloop.m4') -@result{} -forloop(`i', `1', `4', `forloop(`j', `1', `8', ` (i, j)') -') -@result{} (1, 1) (1, 2) (1, 3) (1, 4) (1, 5) (1, 6) (1, 7) (1, 8) -@result{} (2, 1) (2, 2) (2, 3) (2, 4) (2, 5) (2, 6) (2, 7) (2, 8) -@result{} (3, 1) (3, 2) (3, 3) (3, 4) (3, 5) (3, 6) (3, 7) (3, 8) -@result{} (4, 1) (4, 2) (4, 3) (4, 4) (4, 5) (4, 6) (4, 7) (4, 8) -@result{} -@end example - -The implementation of the @code{forloop} macro is fairly -straightforward. The @code{forloop} macro itself is simply a wrapper, -which saves the previous definition of the first argument, calls the -internal macro @code{@w{_forloop}}, and re-establishes the saved -definition of the first argument. - -The macro @code{@w{_forloop}} expands the fourth argument once, and -tests to see if the iterator has reached the final value. If it has -not finished, it increments the iterator (using the predefined macro -@code{incr}, @pxref{Incr}), and recurses. - -Here is an actual implementation of @code{forloop}, distributed as -@file{m4-@value{VERSION}/@/doc/examples/@/forloop.m4} in this package: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -undivert(`forloop.m4')dnl -@result{}divert(`-1') -@result{}# forloop(var, from, to, stmt) - simple version -@result{}define(`forloop', `pushdef(`$1', `$2')_forloop($@@)popdef(`$1')') -@result{}define(`_forloop', -@result{} `$4`'ifelse($1, `$3', `', `define(`$1', incr($1))$0($@@)')') -@result{}divert`'dnl -@end example - -Notice the careful use of quotes. Certain macro arguments are left -unquoted, each for its own reason. Try to find out @emph{why} these -arguments are left unquoted, and see what happens if they are quoted. -(As presented, these two macros are useful but not very robust for -general use. They lack even basic error handling for cases like -@var{start} less than @var{end}, @var{end} not numeric, or -@var{iterator} not being a macro name. See if you can improve these -macros; or @pxref{Improved forloop, , Answers}). - -@node Foreach -@section Iteration by list contents - -@cindex for each loops -@cindex loops, list iteration -@cindex iterating over lists -Here is an example of a loop macro that implements list iteration. - -@deffn Composite foreach (@var{iterator}, @var{paren-list}, @var{text}) -@deffnx Composite foreachq (@var{iterator}, @var{quote-list}, @var{text}) -Takes the name in @var{iterator}, which must be a valid macro name, and -successively assign it each value from @var{paren-list} or -@var{quote-list}. In @code{foreach}, @var{paren-list} is a -comma-separated list of elements contained in parentheses. In -@code{foreachq}, @var{quote-list} is a comma-separated list of elements -contained in a quoted string. For each assignment to @var{iterator}, -append @var{text} to the overall expansion. @var{text} may refer to -@var{iterator}. Any definition of @var{iterator} prior to this -invocation is restored. -@end deffn - -As an example, this displays each word in a list inside of a sentence, -using an implementation of @code{foreach} distributed as -@file{m4-@value{VERSION}/@/doc/examples/@/foreach.m4}, and @code{foreachq} -in @file{m4-@value{VERSION}/@/doc/examples/@/foreachq.m4}. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`foreach.m4') -@result{} -foreach(`x', (foo, bar, foobar), `Word was: x -')dnl -@result{}Word was: foo -@result{}Word was: bar -@result{}Word was: foobar -include(`foreachq.m4') -@result{} -foreachq(`x', `foo, bar, foobar', `Word was: x -')dnl -@result{}Word was: foo -@result{}Word was: bar -@result{}Word was: foobar -@end example - -It is possible to be more complex; each element of the @var{paren-list} -or @var{quote-list} can itself be a list, to pass as further arguments -to a helper macro. This example generates a shell case statement: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`foreach.m4') -@result{} -define(`_case', ` $1) - $2=" $1";; -')dnl -define(`_cat', `$1$2')dnl -case $`'1 in -@result{}case $1 in -foreach(`x', `(`(`a', `vara')', `(`b', `varb')', `(`c', `varc')')', - `_cat(`_case', x)')dnl -@result{} a) -@result{} vara=" a";; -@result{} b) -@result{} varb=" b";; -@result{} c) -@result{} varc=" c";; -esac -@result{}esac -@end example - -The implementation of the @code{foreach} macro is a bit more involved; -it is a wrapper around two helper macros. First, @code{@w{_arg1}} is -needed to grab the first element of a list. Second, -@code{@w{_foreach}} implements the recursion, successively walking -through the original list. Here is a simple implementation of -@code{foreach}: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -undivert(`foreach.m4')dnl -@result{}divert(`-1') -@result{}# foreach(x, (item_1, item_2, ..., item_n), stmt) -@result{}# parenthesized list, simple version -@result{}define(`foreach', `pushdef(`$1')_foreach($@@)popdef(`$1')') -@result{}define(`_arg1', `$1') -@result{}define(`_foreach', `ifelse(`$2', `()', `', -@result{} `define(`$1', _arg1$2)$3`'$0(`$1', (shift$2), `$3')')') -@result{}divert`'dnl -@end example - -Unfortunately, that implementation is not robust to macro names as list -elements. Each iteration of @code{@w{_foreach}} is stripping another -layer of quotes, leading to erratic results if list elements are not -already fully expanded. The first cut at implementing @code{foreachq} -takes this into account. Also, when using quoted elements in a -@var{paren-list}, the overall list must be quoted. A @var{quote-list} -has the nice property of requiring fewer characters to create a list -containing the same quoted elements. To see the difference between the -two macros, we attempt to pass double-quoted macro names in a list, -expecting the macro name on output after one layer of quotes is removed -during list iteration and the final layer removed during the final -rescan: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -define(`a', `1')define(`b', `2')define(`c', `3') -@result{} -include(`foreach.m4') -@result{} -include(`foreachq.m4') -@result{} -foreach(`x', `(``a'', ``(b'', ``c)'')', `x -') -@result{}1 -@result{}(2)1 -@result{} -@result{}, x -@result{}) -foreachq(`x', ```a'', ``(b'', ``c)''', `x -')dnl -@result{}a -@result{}(b -@result{}c) -@end example - -Obviously, @code{foreachq} did a better job; here is its implementation: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -undivert(`foreachq.m4')dnl -@result{}include(`quote.m4')dnl -@result{}divert(`-1') -@result{}# foreachq(x, `item_1, item_2, ..., item_n', stmt) -@result{}# quoted list, simple version -@result{}define(`foreachq', `pushdef(`$1')_foreachq($@@)popdef(`$1')') -@result{}define(`_arg1', `$1') -@result{}define(`_foreachq', `ifelse(quote($2), `', `', -@result{} `define(`$1', `_arg1($2)')$3`'$0(`$1', `shift($2)', `$3')')') -@result{}divert`'dnl -@end example - -Notice that @code{@w{_foreachq}} had to use the helper macro -@code{quote} defined earlier (@pxref{Shift}), to ensure that the -embedded @code{ifelse} call does not go haywire if a list element -contains a comma. Unfortunately, this implementation of @code{foreachq} -has its own severe flaw. Whereas the @code{foreach} implementation was -linear, this macro is quadratic in the number of list elements, and is -much more likely to trip up the limit set by the command line option -@option{--nesting-limit} (or @option{-L}, @pxref{Limits control, , -Invoking m4}). Additionally, this implementation does not expand -@samp{defn(`@var{iterator}')} very well, when compared with -@code{foreach}. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`foreach.m4')include(`foreachq.m4') -@result{} -foreach(`name', `(`a', `b')', ` defn(`name')') -@result{} a b -foreachq(`name', ``a', `b'', ` defn(`name')') -@result{} _arg1(`a', `b') _arg1(shift(`a', `b')) -@end example - -It is possible to have robust iteration with linear behavior and sane -@var{iterator} contents for either list style. See if you can learn -from the best elements of both of these implementations to create robust -macros (or @pxref{Improved foreach, , Answers}). - -@node Stacks -@section Working with definition stacks - -@cindex definition stack -@cindex pushdef stack -@cindex stack, macro definition -Thanks to @code{pushdef}, manipulation of a stack is an intrinsic -operation in @code{m4}. Normally, only the topmost definition in a -stack is important, but sometimes, it is desirable to manipulate the -entire definition stack. - -@deffn Composite stack_foreach (@var{macro}, @var{action}) -@deffnx Composite stack_foreach_lifo (@var{macro}, @var{action}) -For each of the @code{pushdef} definitions associated with @var{macro}, -invoke the macro @var{action} with a single argument of that definition. -@code{stack_foreach} visits the oldest definition first, while -@code{stack_foreach_lifo} visits the current definition first. -@var{action} should not modify or dereference @var{macro}. There are a -few special macros, such as @code{defn}, which cannot be used as the -@var{macro} parameter. -@end deffn - -A sample implementation of these macros is distributed in the file -@file{m4-@value{VERSION}/@/doc/examples/@/stack.m4}. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`stack.m4') -@result{} -pushdef(`a', `1')pushdef(`a', `2')pushdef(`a', `3') -@result{} -define(`show', ``$1' -') -@result{} -stack_foreach(`a', `show')dnl -@result{}1 -@result{}2 -@result{}3 -stack_foreach_lifo(`a', `show')dnl -@result{}3 -@result{}2 -@result{}1 -@end example - -Now for the implementation. Note the definition of a helper macro, -@code{_stack_reverse}, which destructively swaps the contents of one -stack of definitions into the reverse order in the temporary macro -@samp{tmp-$1}. By calling the helper twice, the original order is -restored back into the macro @samp{$1}; since the operation is -destructive, this explains why @samp{$1} must not be modified or -dereferenced during the traversal. The caller can then inject -additional code to pass the definition currently being visited to -@samp{$2}. The choice of helper names is intentional; since @samp{-} is -not valid as part of a macro name, there is no risk of conflict with a -valid macro name, and the code is guaranteed to use @code{defn} where -necessary. Finally, note that any macro used in the traversal of a -@code{pushdef} stack, such as @code{pushdef} or @code{defn}, cannot be -handled by @code{stack_foreach}, since the macro would temporarily be -undefined during the algorithm. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -undivert(`stack.m4')dnl -@result{}divert(`-1') -@result{}# stack_foreach(macro, action) -@result{}# Invoke ACTION with a single argument of each definition -@result{}# from the definition stack of MACRO, starting with the oldest. -@result{}define(`stack_foreach', -@result{}`_stack_reverse(`$1', `tmp-$1')'dnl -@result{}`_stack_reverse(`tmp-$1', `$1', `$2(defn(`$1'))')') -@result{}# stack_foreach_lifo(macro, action) -@result{}# Invoke ACTION with a single argument of each definition -@result{}# from the definition stack of MACRO, starting with the newest. -@result{}define(`stack_foreach_lifo', -@result{}`_stack_reverse(`$1', `tmp-$1', `$2(defn(`$1'))')'dnl -@result{}`_stack_reverse(`tmp-$1', `$1')') -@result{}define(`_stack_reverse', -@result{}`ifdef(`$1', `pushdef(`$2', defn(`$1'))$3`'popdef(`$1')$0($@@)')') -@result{}divert`'dnl -@end example - -@node Composition -@section Building macros with macros - -@cindex macro composition -@cindex composing macros -Since m4 is a macro language, it is possible to write macros that -can build other macros. First on the list is a way to automate the -creation of blind macros. - -@cindex macro, blind -@cindex blind macro -@deffn Composite define_blind (@var{name}, @ovar{value}) -Defines @var{name} as a blind macro, such that @var{name} will expand to -@var{value} 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. -@end 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 -@code{define_blind}, 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 -@code{_define_blind}. When composing macros, it is a common idiom to -need a helper macro to concatenate text that forms parameters in the -composed macro, rather than interpreting the text as a parameter of the -composing macro. - -As for the limitation against using @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 -@code{define_blind} to rename it just adds another layer of -@code{ifelse}, occupying memory and slowing down execution. And if a -macro is a builtin, then it would result in an attempt to define a macro -consisting of both text and a builtin token; this is not supported, and -the builtin token is flattened to an empty string. - -With that explanation, here's the definition, and some sample usage. -Notice that @code{define_blind} is itself a blind macro. - -@example -$ @kbd{m4 -d} -define(`define_blind', `ifelse(`$#', `0', ``$0'', -`_$0(`$1', `$2', `$'`#', `$'`0')')') -@result{} -define(`_define_blind', `define(`$1', -`ifelse(`$3', `0', ``$4'', `$2')')') -@result{} -define_blind -@result{}define_blind -define_blind(`foo', `arguments were $*') -@result{} -foo -@result{}foo -foo(`bar') -@result{}arguments were bar -define(`blah', defn(`foo')) -@result{} -blah -@result{}blah -blah(`a', `b') -@result{}arguments were a,b -defn(`blah') -@result{}ifelse(`$#', `0', ``$0'', `arguments were $*') -@end example - -@cindex currying arguments -@cindex argument currying -Another interesting composition tactic is argument @dfn{currying}, or -factoring a macro that takes multiple arguments for use in a context -that provides exactly one argument. - -@deffn Composite curry (@var{macro}, @dots{}) -Expand to a macro call that takes exactly one argument, then appends -that argument to the original arguments and invokes @var{macro} with the -resulting list of arguments. -@end deffn - -A demonstration of currying makes the intent of this macro a little more -obvious. The macro @code{stack_foreach} mentioned earlier is an example -of a context that provides exactly one argument to a macro name. But -coupled with currying, we can invoke @code{reverse} with two arguments -for each definition of a macro stack. This example uses the file -@file{m4-@value{VERSION}/@/doc/examples/@/curry.m4} included in the -distribution. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`curry.m4')include(`stack.m4') -@result{} -define(`reverse', `ifelse(`$#', `0', , `$#', `1', ``$1'', - `reverse(shift($@@)), `$1'')') -@result{} -pushdef(`a', `1')pushdef(`a', `2')pushdef(`a', `3') -@result{} -stack_foreach(`a', `:curry(`reverse', `4')') -@result{}:1, 4:2, 4:3, 4 -curry(`curry', `reverse', `1')(`2')(`3') -@result{}3, 2, 1 -@end example - -Now for the implementation. Notice how @code{curry} leaves off with a -macro name but no open parenthesis, while still in the middle of -collecting arguments for @samp{$1}. The macro @code{_curry} is the -helper macro that takes one argument, then adds it to the list and -finally supplies the closing parenthesis. The use of a comma inside the -@code{shift} call allows currying to also work for a macro that takes -one argument, although it often makes more sense to invoke that macro -directly rather than going through @code{curry}. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -undivert(`curry.m4')dnl -@result{}divert(`-1') -@result{}# curry(macro, args) -@result{}# Expand to a macro call that takes one argument, then invoke -@result{}# macro(args, extra). -@result{}define(`curry', `$1(shift($@@,)_$0') -@result{}define(`_curry', ``$1')') -@result{}divert`'dnl -@end example - -Unfortunately, with M4 1.4.x, @code{curry} is unable to handle builtin -tokens, which are silently flattened to the empty string when passed -through another text macro. The following example demonstrates a usage -of @code{curry} that works in M4 1.6, but is not portable to earlier -versions: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`curry.m4') -@result{} -curry(`define', `mylen')(defn(`len')) -@result{} -mylen(`abc') -@result{}3 -@end example - -@cindex renaming macros -@cindex copying macros -@cindex macros, copying -Putting the last few concepts together, it is possible to copy or rename -an entire stack of macro definitions. - -@deffn Composite copy (@var{source}, @var{dest}) -@deffnx Composite rename (@var{source}, @var{dest}) -Ensure that @var{dest} is undefined, then define it to the same stack of -definitions currently in @var{source}. @code{copy} leaves @var{source} -unchanged, while @code{rename} undefines @var{source}. There are only a -few macros, such as @code{copy} or @code{defn}, which cannot be copied -via this macro. -@end deffn - -The implementation is relatively straightforward (although since it uses -@code{curry}, it is unable to copy builtin macros when used with M4 -1.4.x. See if you can design a portable version that works across all -M4 versions, or @pxref{Improved copy, , Answers}). - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`curry.m4')include(`stack.m4') -@result{} -define(`rename', `copy($@@)undefine(`$1')')dnl -define(`copy', `ifdef(`$2', `errprint(`$2 already defined -')m4exit(`1')', - `stack_foreach(`$1', `curry(`pushdef', `$2')')')')dnl -pushdef(`a', `1')pushdef(`a', defn(`divnum'))pushdef(`a', `2') -@result{} -copy(`a', `b') -@result{} -rename(`b', `c') -@result{} -a b c -@result{}2 b 2 -popdef(`a', `c')a c -@result{}0 0 -popdef(`a', `c')a c -@result{}1 1 -@end example - -@node Debugging -@chapter How to debug macros and input - -@cindex debugging macros -@cindex macros, debugging -When writing macros for @code{m4}, they often do not work as intended on -the first try (as is the case with most programming languages). -Fortunately, there is support for macro debugging in @code{m4}. - -@menu -* Dumpdef:: Displaying macro definitions -* Trace:: Tracing macro calls -* Debugmode:: Controlling debugging options -* Debuglen:: Limiting debug output -* Debugfile:: Saving debugging output -@end menu - -@node Dumpdef -@section Displaying macro definitions - -@cindex displaying macro definitions -@cindex macros, displaying definitions -@cindex definitions, displaying macro -@cindex standard error, output to -If you want to see what a name expands into, you can use the builtin -@code{dumpdef}: - -@deffn {Builtin (m4)} dumpdef (@ovar{name@dots{}}) -Accepts any number of arguments. If called without any arguments, it -displays the definitions of all known names, otherwise it displays the -definitions of each @var{name} given, sorted by name. If a @var{name} -is undefined, the @samp{d} debug level controls whether a warning is -issued (@pxref{Debugmode}). Likewise, the @samp{o} debug level controls -whether the output is issued to standard error or the current debug -file (@pxref{Debugfile}). - -The expansion of @code{dumpdef} is void. -@end deffn - -@example -$ @kbd{m4 -d} -define(`foo', `Hello world.') -@result{} -dumpdef(`foo') -@error{}foo:@tabchar{}`Hello world.' -@result{} -dumpdef(`define') -@error{}define:@tabchar{} -@result{} -@end example - -The last example shows how builtin macros definitions are displayed. -The definition that is dumped corresponds to what would occur if the -macro were to be called at that point, even if other definitions are -still live due to redefining a macro during argument collection. - -@example -$ @kbd{m4 -d} -pushdef(`f', ``$0'1')pushdef(`f', ``$0'2') -@result{} -f(popdef(`f')dumpdef(`f')) -@error{}f:@tabchar{}``$0'1' -@result{}f2 -f(popdef(`f')dumpdef(`f')) -@error{}m4:stdin:3: warning: dumpdef: undefined macro 'f' -@result{}f1 -debugmode(`-d') -@result{} -dumpdef(`f') -@result{} -@end example - -@xref{Debugmode}, for information on how the @samp{m}, @samp{q}, and -@samp{s} flags affect the details of the display. Remember, the -@samp{q} flag is implied when the @option{--debug} option (@option{-d}, -@pxref{Debugging options, , Invoking m4}) is used in the command line -without arguments. Also, @option{--debuglen} (@pxref{Debuglen}) can affect -output, by truncating longer strings (but not builtin and module names). - -@comment options: -ds -l3 -@example -$ @kbd{m4 -ds -l 3} -pushdef(`foo', `1 long string') -@result{} -pushdef(`foo', defn(`divnum')) -@result{} -pushdef(`foo', `3') -@result{} -debugmode(`+m') -@result{} -dumpdef(`foo', `dnl', `indir', `__gnu__') -@error{}__gnu__:@tabchar{}@{gnu@} -@error{}dnl:@tabchar{}@{m4@} -@error{}foo:@tabchar{}3, @{m4@}, 1 l... -@error{}indir:@tabchar{}@{gnu@} -@result{} -debugmode(`-ms')debugmode(`+q') -@result{} -dumpdef(`foo') -@error{}foo:@tabchar{}`3' -@result{} -@end example - -@node Trace -@section Tracing macro calls - -@cindex tracing macro expansion -@cindex macro expansion, tracing -@cindex expansion, tracing macro -@cindex standard error, output to -It is possible to trace macro calls and expansions through the builtins -@code{traceon} and @code{traceoff}: - -@deffn {Builtin (m4)} traceon (@ovar{names@dots{}}) -@deffnx {Builtin (m4)} traceoff (@ovar{names@dots{}}) -When called without any arguments, @code{traceon} and @code{traceoff} -will turn tracing on and off, respectively, for all macros, identical to -using the @samp{t} flag of @code{debugmode} (@pxref{Debugmode}). - -When called with arguments, only the macros listed in @var{names} are -affected, whether or not they are currently defined. A macro's -expansion will be traced if global tracing is on, or if the individual -macro tracing flag is set; to avoid tracing a macro, both the global -flag and the macro must have tracing off. - -The expansion of @code{traceon} and @code{traceoff} is void. -@end deffn - -Whenever a traced macro is called and the arguments have been collected, -the call is displayed. If the expansion of the macro call is not void, -the expansion can be displayed after the call. The output is printed -to the current debug file (defaulting to standard error, -@pxref{Debugfile}). - -@example -$ @kbd{m4 -d} -define(`foo', `Hello World.') -@result{} -define(`echo', `$@@') -@result{} -traceon(`foo', `echo') -@result{} -foo -@error{}m4trace: -1- foo -> `Hello World.' -@result{}Hello World. -echo(`gnus', `and gnats') -@error{}m4trace: -1- echo(`gnus', `and gnats') -> ``gnus',`and gnats'' -@result{}gnus,and gnats -@end example - -The number between dashes is the depth of the expansion. It is one most -of the time, signifying an expansion at the outermost level, but it -increases when macro arguments contain unquoted macro calls. The -maximum number that will appear between dashes is controlled by the -option @option{--nesting-limit} (or @option{-L}, @pxref{Limits control, -, Invoking m4}). Additionally, the option @option{--trace} (or -@option{-t}) can be used to invoke @code{traceon(@var{name})} before -parsing input. - -@comment options: -d-V -L3 -tifelse -@comment status: 1 -@example -$ @kbd{m4 -L 3 -t ifelse} -ifelse(`one level') -@error{}m4trace: -1- ifelse -@result{} -ifelse(ifelse(ifelse(`three levels'))) -@error{}m4trace: -3- ifelse -@error{}m4trace: -2- ifelse -@error{}m4trace: -1- ifelse -@result{} -ifelse(ifelse(ifelse(ifelse(`four levels')))) -@error{}m4:stdin:3: recursion limit of 3 exceeded, use -L to change it -@end example - -Tracing by name is an attribute that is preserved whether the macro is -defined or not. This allows the selection of macros to trace before -those macros are defined. - -@example -$ @kbd{m4 -d} -traceoff(`foo') -@result{} -traceon(`foo') -@result{} -foo -@result{}foo -defn(`foo') -@error{}m4:stdin:4: warning: defn: undefined macro 'foo' -@result{} -undefine(`foo') -@error{}m4:stdin:5: warning: undefine: undefined macro 'foo' -@result{} -pushdef(`foo') -@result{} -popdef(`foo') -@result{} -popdef(`foo') -@error{}m4:stdin:8: warning: popdef: undefined macro 'foo' -@result{} -define(`foo', `bar') -@result{} -foo -@error{}m4trace: -1- foo -> `bar' -@result{}bar -undefine(`foo') -@result{} -ifdef(`foo', `yes', `no') -@result{}no -indir(`foo') -@error{}m4:stdin:13: warning: indir: undefined macro 'foo' -@result{} -define(`foo', `blah') -@result{} -foo -@error{}m4trace: -1- foo -> `blah' -@result{}blah -@end example - -Tracing even works on builtins. However, @code{defn} (@pxref{Defn}) -does not transfer tracing status. - -@example -$ @kbd{m4 -d} -traceon(`traceon') -@result{} -traceon(`traceoff') -@error{}m4trace: -1- traceon(`traceoff') -> `' -@result{} -traceoff(`traceoff') -@error{}m4trace: -1- traceoff(`traceoff') -> `' -@result{} -traceoff(`traceon') -@result{} -traceon(`eval', `m4_divnum') -@result{} -define(`m4_eval', defn(`eval')) -@result{} -define(`m4_divnum', defn(`divnum')) -@result{} -eval(divnum) -@error{}m4trace: -1- eval(`0') -> `0' -@result{}0 -m4_eval(m4_divnum) -@error{}m4trace: -2- m4_divnum -> `0' -@result{}0 -@end example - -As of GNU M4 2.0, named macro tracing is independent of global -tracing status; calling @code{traceoff} without arguments turns off the -global trace flag, but does not turn off tracing for macros where -tracing was requested by name. Likewise, calling @code{traceon} without -arguments will affect tracing of macros that are not defined yet. This -behavior matches traditional implementations of @code{m4}. - -@example -$ @kbd{m4 -d} -traceon -@result{} -define(`foo', `bar') -@error{}m4trace: -1- define(`foo', `bar') -> `' -@result{} -foo # traced, even though foo was not defined at traceon -@error{}m4trace: -1- foo -> `bar' -@result{}bar # traced, even though foo was not defined at traceon -traceoff(`foo') -@error{}m4trace: -1- traceoff(`foo') -> `' -@result{} -foo # traced, since global tracing is still on -@error{}m4trace: -1- foo -> `bar' -@result{}bar # traced, since global tracing is still on -traceon(`foo') -@error{}m4trace: -1- traceon(`foo') -> `' -@result{} -traceoff -@error{}m4trace: -1- traceoff -> `' -@result{} -foo # traced, since foo is now traced by name -@error{}m4trace: -1- foo -> `bar' -@result{}bar # traced, since foo is now traced by name -traceoff(`foo') -@result{} -foo # untraced -@result{}bar # untraced -@end example - -However, GNU M4 prior to 2.0 had slightly different -semantics, where @code{traceon} without arguments only affected symbols -that were defined at that moment, and @code{traceoff} without arguments -stopped all tracing, even when tracing was requested by macro name. The -addition of the macro @code{m4symbols} (@pxref{M4symbols}) in 2.0 makes it -possible to write a file that approximates the older semantics -regardless of which version of GNU M4 is in use. - -@comment options: -d-V -@example -$ @kbd{m4} -ifdef(`m4symbols', - `define(`traceon', `ifelse(`$#', `0', `builtin(`traceon', m4symbols)', - `builtin(`traceon', $@@)')')dnl -define(`traceoff', `ifelse(`$#', `0', - `builtin(`traceoff')builtin(`traceoff', m4symbols)', - `builtin(`traceoff', $@@)')')')dnl -define(`a', `1') -@result{} -traceon # called before b is defined, so b is not traced -@result{} # called before b is defined, so b is not traced -define(`b', `2') -@error{}m4trace: -1- define -@result{} -a b -@error{}m4trace: -1- a -@result{}1 2 -traceon(`b') -@error{}m4trace: -1- traceon -@error{}m4trace: -1- ifelse -@error{}m4trace: -1- builtin -@result{} -a b -@error{}m4trace: -1- a -@error{}m4trace: -1- b -@result{}1 2 -traceoff # stops tracing b, even though it was traced by name -@error{}m4trace: -1- traceoff -@error{}m4trace: -1- ifelse -@error{}m4trace: -1- builtin -@error{}m4trace: -2- m4symbols -@error{}m4trace: -1- builtin -@result{} # stops tracing b, even though it was traced by name -a b -@result{}1 2 -@end example - -@xref{Debugmode}, for information on controlling the details of the -display. The format of the trace output is not specified by -POSIX, and varies between implementations of @code{m4}. - -Starting with M4 1.6, tracing also works via @code{indir} -(@pxref{Indir}). However, since tracing is an attribute tracked by -macro names, and @code{builtin} bypasses macro names (@pxref{Builtin}), -it is not possible for @code{builtin} to trace which subsidiary builtin -it invokes. If you are worried about tracking all invocations of a -given builtin, you should also trace @code{builtin}, or enable global -tracing (the @samp{t} debug level, @pxref{Debugmode}). - -@example -$ @kbd{m4 -d} -define(`my_defn', defn(`defn'))undefine(`defn') -@result{} -define(`foo', `bar')traceon(`foo', `defn', `my_defn') -@result{} -foo -@error{}m4trace: -1- foo -> `bar' -@result{}bar -indir(`foo') -@error{}m4trace: -1- foo -> `bar' -@result{}bar -my_defn(`foo') -@error{}m4trace: -1- my_defn(`foo') -> ``bar'' -@result{}bar -indir(`my_defn', `foo') -@error{}m4trace: -1- my_defn(`foo') -> ``bar'' -@result{}bar -builtin(`defn', `foo') -@result{}bar -debugmode(`+cxt') -@result{} -builtin(`defn', builtin(`shift', `', `foo')) -@error{}m4trace: -1- id 12: builtin ... = -@error{}m4trace: -2- id 13: builtin ... = -@error{}m4trace: -2- id 13: builtin(`shift', `', `foo') -> ``foo'' -@error{}m4trace: -1- id 12: builtin(`defn', `foo') -> ``bar'' -@result{}bar -indir(`my_defn', indir(`shift', `', `foo')) -@error{}m4trace: -1- id 14: indir ... = -@error{}m4trace: -2- id 15: indir ... = -@error{}m4trace: -2- id 15: shift ... = -@error{}m4trace: -2- id 15: shift(`', `foo') -> ``foo'' -@error{}m4trace: -2- id 15: indir(`shift', `', `foo') -> ``foo'' -@error{}m4trace: -1- id 14: my_defn ... = -@error{}m4trace: -1- id 14: my_defn(`foo') -> ``bar'' -@error{}m4trace: -1- id 14: indir(`my_defn', `foo') -> ``bar'' -@result{}bar -@end example - -@node Debugmode -@section Controlling debugging options - -@cindex controlling debugging output -@cindex debugging output, controlling -The @option{--debug} option to @code{m4} (also spelled -@option{--debugmode} or @option{-d}, @pxref{Debugging options, , -Invoking m4}) controls the amount of details presented in three -categories of output. Trace output is requested by @code{traceon} -(@pxref{Trace}), and each line is prefixed by @samp{m4trace:} in -relation to a macro invocation. Debug output tracks useful events not -associated with a macro invocation, and each line is prefixed by -@samp{m4debug:}. Finally, @code{dumpdef} (@pxref{Dumpdef}) output is -affected, with no prefix added to the output lines. - -The @var{flags} following the option can be one or more of the -following: - -@table @code -@item a -In trace output, show the actual arguments that were collected before -invoking the macro. Arguments are subject to length truncation -specified by @code{debuglen} (@pxref{Debuglen}). - -@item c -In trace output, show an additional line for each macro call, when the -macro is seen, but before the arguments are collected, and show the -definition of the macro that will be used for the expansion. By -default, only one line is printed, after all arguments are collected and -the expansion determined. The definition is subject to length -truncation specified by @code{debuglen} (@pxref{Debuglen}). This is -often used with the @samp{x} flag. - -@item d -Output a warning on any attempt to dereference an undefined macro via -@code{builtin}, @code{defn}, @code{dumpdef}, @code{indir}, -@code{popdef}, or @code{undefine}. Note that @code{indef}, -@code{m4symbols}, -@code{traceon}, and @code{traceoff} do not dereference undefined macros. -Like any other warning, the warnings enabled by this flag go to standard -error regardless of the current @code{debugfile} setting, and will -change exit status if the command line option @option{--fatal-warnings} -was specified. This flag is useful in diagnosing spelling mistakes in -macro names. It is enabled by default when neither @option{--debug} nor -@option{--fatal-warnings} are specified on the command line. - -@item e -In trace output, show the expansion of each macro call. The expansion -is subject to length truncation specified by @code{debuglen} -(@pxref{Debuglen}). - -@item f -In debug and trace output, include the name of the current input file in -the output line. - -@item i -In debug output, print a message each time the current input file is -changed. - -@item l -In debug and trace output, include the current input line number in the -output line. - -@item m -In debug output, print a message each time a module is manipulated -(@pxref{Modules}). In trace output when the @samp{c} flag is in effect, -and in dumpdef output, follow builtin macros with their module name, -surrounded by braces (@samp{@{@}}). - -@item o -Output @code{dumpdef} data to standard error instead of the current -debug file. This can be useful when post-processing trace output, where -interleaving dumpdef and trace output can cause ambiguities. - -@item p -In debug output, print a message when a named file is found through the -path search mechanism (@pxref{Search Path}), giving the actual file name -used. - -@item q -In trace and dumpdef output, quote actual arguments and macro expansions -in the display with the current quotes. This is useful in connection -with the @samp{a} and @samp{e} flags above. - -@item s -In dumpdef output, show the entire stack of definitions associated with -a symbol via @code{pushdef}. - -@item t -In trace output, trace all macro calls made in this invocation of -@code{m4}. This is equivalent to using @code{traceon} without -arguments. - -@item x -In trace output, add a unique `macro call id' to each line of the trace -output. This is useful in connection with the @samp{c} flag above, to -match where a macro is first recognized with where it is finally -expanded, in spite of intermediate expansions that occur while -collecting arguments. It can also be used in isolation to determine how -many macros have been expanded. - -@item V -A shorthand for all of the above flags. -@end table - -As special cases, if @var{flags} starts with a @samp{+}, the named flags -are enabled without impacting other flags, and if it starts with a -@samp{-}, the named flags are disabled without impacting other flags. -Without either of these starting characters, @var{flags} simply replaces -the previous setting. -@comment FIXME - should we accept usage like debugmode(+fl-q)? Also, -@comment should we add debugmode(?) which expands to the current -@comment enabled flags, and debugmode(e?) which expands to e if e is -@comment currently enabled? - -If no flags are specified with the @option{--debug} option, the default is -@samp{+adeq}. Many examples in this manual show their output using -default flags. - -@cindex GNU extensions -There is a builtin macro @code{debugmode}, which allows on-the-fly control of -the debugging output format: - -@deffn {Builtin (gnu)} debugmode (@ovar{flags}) -The argument @var{flags} should be a subset of the letters listed above. -If no argument is present, all debugging flags are cleared (as if -@var{flags} were an explicit @samp{-V}). With an empty argument, the -most common flags are enabled (as if @var{flags} were an explicit -@samp{+adeq}). If an unknown flag is encountered, an error is issued. - -The expansion of @code{debugmode} is void. -@end deffn - -@comment options: -d-V -@example -$ @kbd{m4} -define(`foo', `FOO$1') -@result{} -traceon(`foo', `divnum') -@result{} -debugmode()dnl same as debugmode(`+adeq') -foo -@error{}m4trace: -1- foo -> `FOO' -@result{}FOO -debugmode(`V')debugmode(`-q') -@error{}m4trace:stdin:5: -1- id 7: debugmode ... = @{gnu@} -@error{}m4trace:stdin:5: -1- id 7: debugmode(`-q') -> `' -@result{} -foo( -`BAR') -@error{}m4trace:stdin:6: -1- id 8: foo ... = FOO$1 -@error{}m4trace:stdin:6: -1- id 8: foo(BAR) -> FOOBAR -@result{}FOOBAR -debugmode`'dnl same as debugmode(`-V') -@error{}m4trace:stdin:8: -1- id 9: debugmode ... = @{gnu@} -@error{}m4trace:stdin:8: -1- id 9: debugmode ->@w{ } -foo -@error{}m4trace: -1- foo -@result{}FOO -debugmode(`+clmx') -@result{} -foo(divnum) -@error{}m4trace:11: -1- id 13: foo ... = FOO$1 -@error{}m4trace:11: -2- id 14: divnum ... = @{m4@} -@error{}m4trace:11: -2- id 14: divnum -@error{}m4trace:11: -1- id 13: foo -@result{}FOO0 -debugmode(`-m') -@result{} -@end example - -This example shows the effects of the debug flags that are not related -to macro tracing. - -@comment examples -@comment options: -dip -@example -$ @kbd{m4 -dip -I doc/examples} -@error{}m4debug: input read from 'stdin' -define(`foo', `m4wrap(`wrapped text -')dnl') -@result{} -include(`incl.m4')dnl -@error{}m4debug: path search for 'incl.m4' found 'doc/examples/incl.m4' -@error{}m4debug: input read from 'doc/examples/incl.m4' -@result{}Include file start -@result{}Include file end -@error{}m4debug: input reverted to stdin, line 3 -^D -@error{}m4debug: input exhausted -@error{}m4debug: input from m4wrap recursion level 1 -@result{}wrapped text -@error{}m4debug: input from m4wrap exhausted -@end example - -@node Debuglen -@section Limiting debug output - -@cindex GNU extensions -@cindex arglength -@cindex debuglen -@cindex limiting trace output length -@cindex trace output, limiting length -@cindex dumpdef output, limiting length -When debugging, sometimes it is desirable to reduce the clutter of -arbitrary-length strings, because the prefix carries enough information -to understand the issues. The builtin macro @code{debuglen}, along with -the command line option counterpart @option{--debuglen} (or @option{-l}, -@pxref{Debugging options, , Invoking m4}), allow on-the-fly control of -debugging string lengths: - -@deffn {Builtin (gnu)} debuglen (@var{len}) -The argument @var{len} is an integer that controls how much of -arbitrary-length strings should be output during trace and dumpdef -output. If specified to a non-zero value, then strings longer than that -length are truncated, and @samp{...} included in the output to show that -truncation took place. A warning is issued if @var{len} cannot be -parsed as an integer. -@comment FIXME - make this understand an optional suffix, similar to how -@comment --debuglen does. Also, we need a section documenting scaling -@comment suffixes. -@comment FIXME - should we allow len to be `?', meaning expand to the -@comment current value? - -The macro @code{debuglen} is recognized only with parameters. -@end deffn - -The following example demonstrates the behavior of length truncation. -Note that each argument and the final result are individually truncated. -Also, the special tokens for builtin functions are not truncated. - -@comment options: -l6 -techo -tdefn -@example -$ @kbd{m4 -d -l 6 -t echo -t defn} -debuglen(`oops') -@error{}m4:stdin:1: warning: debuglen: non-numeric argument 'oops' -@result{} -define(`echo', `$@@') -@result{} -echo(`1', `long string') -@error{}m4trace: -1- echo(`1', `long s...') -> ``1',`l...' -@result{}1,long string -indir(`echo', defn(`changequote')) -@error{}m4trace: -2- defn(`change...') -> `' -@error{}m4trace: -1- echo() -> ``'' -@result{} -debuglen -@result{}debuglen -debuglen(`0') -@result{} -echo(`long string') -@error{}m4trace: -1- echo(`long string') -> ``long string'' -@result{}long string -debuglen(`12') -@result{} -echo(`long string') -@error{}m4trace: -1- echo(`long string') -> ``long string...' -@result{}long string -@end example - -@node Debugfile -@section Saving debugging output - -@cindex saving debugging output -@cindex debugging output, saving -@cindex output, saving debugging -@cindex GNU extensions -Debug and tracing output can be redirected to files using either the -@option{--debugfile} option to @code{m4} (@pxref{Debugging options, , -Invoking m4}), or with the builtin macro @code{debugfile}: - -@deffn {Builtin (gnu)} debugfile (@ovar{file}) -Send all further debug and trace output to @var{file}, opened in append -mode. If @var{file} is the empty string, debug and trace output are -discarded. If @code{debugfile} is called without any arguments, debug -and trace output are sent to standard error. Output from @code{dumpdef} -is sent to this file if the debug level @code{o} is not set -(@pxref{Debugmode}). This does not affect -warnings, error messages, or @code{errprint} output, which are -always sent to standard error. If @var{file} cannot be opened, the -current debug file is unchanged, and an error is issued. - -When the @option{--safer} option (@pxref{Operation modes, , Invoking -m4}) is in effect, @var{file} must be empty or omitted, since otherwise -an input file could cause the modification of arbitrary files. - -The expansion of @code{debugfile} is void. -@end deffn - -@example -$ @kbd{m4 -d} -traceon(`divnum') -@result{} -divnum(`extra') -@error{}m4:stdin:2: warning: divnum: extra arguments ignored: 1 > 0 -@error{}m4trace: -1- divnum(`extra') -> `0' -@result{}0 -debugfile() -@result{} -divnum(`extra') -@error{}m4:stdin:4: warning: divnum: extra arguments ignored: 1 > 0 -@result{}0 -debugfile -@result{} -divnum -@error{}m4trace: -1- divnum -> `0' -@result{}0 -@end example - -Although the @option{--safer} option cripples @code{debugfile} to a -limited subset of capabilities, you may still use the @option{--debugfile} -option from the command line with no restrictions. - -@comment options: --safer --debugfile=trace -tfoo -Dfoo=bar -d+l -@comment status: 1 -@example -$ @kbd{m4 --safer --debugfile trace -t foo -D foo=bar -daelq} -foo # traced to `trace' -@result{}bar # traced to `trace' -debugfile(`file') -@error{}m4:stdin:2: debugfile: disabled by --safer -@result{} -foo # traced to `trace' -@result{}bar # traced to `trace' -debugfile() -@result{} -foo # trace discarded -@result{}bar # trace discarded -debugfile -@result{} -foo # traced to stderr -@error{}m4trace:7: -1- foo -> `bar' -@result{}bar # traced to stderr -undivert(`trace')dnl -@result{}m4trace:1: -1- foo -> `bar' -@result{}m4trace:3: -1- foo -> `bar' -@end example - -Sometimes it is useful to post-process trace output, even though there -is no standardized format for trace output. In this situation, forcing -@code{dumpdef} to output to standard error instead of the default of the -current debug file will avoid any ambiguities between the two types of -output; it also allows debugging via @code{dumpdef} when debug output is -discarded. - -@example -$ @kbd{m4 -d} -traceon(`divnum') -@result{} -divnum -@error{}m4trace: -1- divnum -> `0' -@result{}0 -dumpdef(`divnum') -@error{}divnum:@tabchar{} -@result{} -debugfile(`') -@result{} -divnum -@result{}0 -dumpdef(`divnum') -@result{} -debugmode(`+o') -@result{} -divnum -@result{}0 -dumpdef(`divnum') -@error{}divnum:@tabchar{} -@result{} -@end example - -@node Input Control -@chapter Input control - -This chapter describes various builtin macros for controlling the input -to @code{m4}. - -@menu -* Dnl:: Deleting whitespace in input -* Changequote:: Changing the quote characters -* Changecom:: Changing the comment delimiters -* Changeresyntax:: Changing the regular expression syntax -* Changesyntax:: Changing the lexical structure of the input -* M4wrap:: Saving text until end of input -@end menu - -@node Dnl -@section Deleting whitespace in input - -@cindex deleting whitespace in input -@cindex discarding input -@cindex input, discarding -The builtin @code{dnl} stands for ``Discard to Next Line'': - -@deffn {Builtin (m4)} dnl -All characters, up to and including the next newline, are discarded -without performing any macro expansion. A warning is issued if the end -of the file is encountered without a newline. - -The expansion of @code{dnl} is void. -@end deffn - -It is often used in connection with @code{define}, to remove the -newline that follows the call to @code{define}. Thus - -@example -define(`foo', `Macro `foo'.')dnl A very simple macro, indeed. -foo -@result{}Macro foo. -@end example - -The input up to and including the next newline is discarded, as opposed -to the way comments are treated (@pxref{Comments}), when the command -line option @option{--discard-comments} is not in effect -(@pxref{Operation modes, , Invoking m4}). - -Usually, @code{dnl} is immediately followed by an end of line or some -other whitespace. GNU @code{m4} will produce a warning diagnostic if -@code{dnl} is followed by an open parenthesis. In this case, @code{dnl} -will collect and process all arguments, looking for a matching close -parenthesis. All predictable side effects resulting from this -collection will take place. @code{dnl} will return no output. The -input following the matching close parenthesis up to and including the -next newline, on whatever line containing it, will still be discarded. - -@example -dnl(`args are ignored, but side effects occur', -define(`foo', `like this')) while this text is ignored: undefine(`foo') -@error{}m4:stdin:1: warning: dnl: extra arguments ignored: 2 > 0 -See how `foo' was defined, foo? -@result{}See how foo was defined, like this? -@end example - -If the end of file is encountered without a newline character, a -warning is issued and dnl stops consuming input. - -@example -m4wrap(`m4wrap(`2 hi -')0 hi dnl 1 hi') -@result{} -define(`hi', `HI') -@result{} -^D -@error{}m4:stdin:1: warning: dnl: end of file treated as newline -@result{}0 HI 2 HI -@end example - -@node Changequote -@section Changing the quote characters - -@cindex changing quote delimiters -@cindex quote delimiters, changing -@cindex delimiters, changing -The default quote delimiters can be changed with the builtin -@code{changequote}: - -@deffn {Builtin (m4)} changequote (@dvar{start, `}, @dvar{end, '}) -This sets @var{start} as the new begin-quote delimiter and @var{end} as -the new end-quote delimiter. If both arguments are missing, the default -quotes (@code{`} and @code{'}) are used. If @var{start} is void, then -quoting is disabled. Otherwise, if @var{end} is missing or void, the -default end-quote delimiter (@code{'}) is used. The quote delimiters -can be of any length. - -The expansion of @code{changequote} is void. -@end deffn - -@example -changequote(`[', `]') -@result{} -define([foo], [Macro [foo].]) -@result{} -foo -@result{}Macro foo. -@end example - -The quotation strings can safely contain eight-bit characters. -If no single character is appropriate, @var{start} and @var{end} can be -of any length. Other implementations cap the delimiter length to five -characters, but GNU has no inherent limit. - -@example -changequote(`[[[', `]]]') -@result{} -define([[[foo]]], [[[Macro [[[[[foo]]]]].]]]) -@result{} -foo -@result{}Macro [[foo]]. -@end example - -Calling @code{changequote} with @var{start} as the empty string will -effectively disable the quoting mechanism, leaving no way to quote text. -However, using an empty string is not portable, as some other -implementations of @code{m4} revert to the default quoting, while others -preserve the prior non-empty delimiter. If @var{start} is not empty, -then an empty @var{end} will use the default end-quote delimiter of -@samp{'}, as otherwise, it would be impossible to end a quoted string. -Again, this is not portable, as some other @code{m4} implementations -reuse @var{start} as the end-quote delimiter, while others preserve the -previous non-empty value. Omitting both arguments restores the default -begin-quote and end-quote delimiters; fortunately this behavior is -portable to all implementations of @code{m4}. - -@example -define(`foo', `Macro `FOO'.') -@result{} -changequote(`', `') -@result{} -foo -@result{}Macro `FOO'. -`foo' -@result{}`Macro `FOO'.' -changequote(`,) -@result{} -foo -@result{}Macro FOO. -@end example - -There is no way in @code{m4} to quote a string containing an unmatched -begin-quote, except using @code{changequote} to change the current -quotes. - -If the quotes should be changed from, say, @samp{[} to @samp{[[}, -temporary quote characters have to be defined. To achieve this, two -calls of @code{changequote} must be made, one for the temporary quotes -and one for the new quotes. - -Macros are recognized in preference to the begin-quote string, so if a -prefix of @var{start} can be recognized as part of a potential macro -name, the quoting mechanism is effectively disabled. Unless you use -@code{changesyntax} (@pxref{Changesyntax}), this means that @var{start} -should not begin with a letter, digit, or @samp{_} (underscore). -However, even though quoted strings are not recognized, the quote -characters can still be discerned in macro expansion and in trace -output. - -@example -define(`echo', `$@@') -@result{} -define(`hi', `HI') -@result{} -changequote(`q', `Q') -@result{} -q hi Q hi -@result{}q HI Q HI -echo(hi) -@result{}qHIQ -changequote -@result{} -changequote(`-', `EOF') -@result{} -- hi EOF hi -@result{} hi HI -changequote -@result{} -changequote(`1', `2') -@result{} -hi1hi2 -@result{}hi1hi2 -hi 1hi2 -@result{}HI hi -@end example - -Quotes are recognized in preference to argument collection. In -particular, if @var{start} is a single @samp{(}, then argument -collection is effectively disabled. For portability with other -implementations, it is a good idea to avoid @samp{(}, @samp{,}, and -@samp{)} as the first character in @var{start}. - -@example -define(`echo', `$#:$@@:') -@result{} -define(`hi', `HI') -@result{} -changequote(`(',`)') -@result{} -echo(hi) -@result{}0::hi -changequote -@result{} -changequote(`((', `))') -@result{} -echo(hi) -@result{}1:HI: -echo((hi)) -@result{}0::hi -changequote -@result{} -changequote(`,', `)') -@result{} -echo(hi,hi)bye) -@result{}1:HIhibye: -@end example - -However, if you are not worried about portability, using @samp{(} and -@samp{)} as quoting characters has an interesting property---you can use -it to compute a quoted string containing the expansion of any quoted -text, as long as the expansion results in both balanced quotes and -balanced parentheses. The trick is realizing @code{expand} uses -@samp{$1} unquoted, to trigger its expansion using the normal quoting -characters, but uses extra parentheses to group unquoted commas that -occur in the expansion without consuming whitespace following those -commas. Then @code{_expand} uses @code{changequote} to convert the -extra parentheses back into quoting characters. Note that it takes two -more @code{changequote} invocations to restore the original quotes. -Contrast the behavior on whitespace when using @samp{$*}, via -@code{quote}, to attempt the same task. - -@example -changequote(`[', `]')dnl -define([a], [1, (b)])dnl -define([b], [2])dnl -define([quote], [[$*]])dnl -define([expand], [_$0(($1))])dnl -define([_expand], - [changequote([(], [)])$1changequote`'changequote(`[', `]')])dnl -expand([a, a, [a, a], [[a, a]]]) -@result{}1, (2), 1, (2), a, a, [a, a] -quote(a, a, [a, a], [[a, a]]) -@result{}1,(2),1,(2),a, a,[a, a] -@end example - -If @var{end} is a prefix of @var{start}, the end-quote will be -recognized in preference to a nested begin-quote. In particular, -changing the quotes to have the same string for @var{start} and -@var{end} disables nesting of quotes. When quote nesting is disabled, -it is impossible to double-quote strings across macro expansions, so -using the same string is not done very often. - -@example -define(`hi', `HI') -@result{} -changequote(`""', `"') -@result{} -""hi"""hi" -@result{}hihi -""hi" ""hi" -@result{}hi hi -""hi"" "hi" -@result{}hi" "HI" -changequote -@result{} -`hi`hi'hi' -@result{}hi`hi'hi -changequote(`"', `"') -@result{} -"hi"hi"hi" -@result{}hiHIhi -@end example - -It is an error if the end of file occurs within a quoted string. - -@comment status: 1 -@example -`hello world' -@result{}hello world -`dangling quote -^D -@error{}m4:stdin:2: end of file in string -@end example - -@comment status: 1 -@example -ifelse(`dangling quote -^D -@error{}m4:stdin:1: ifelse: end of file in string -@end example - -@node Changecom -@section Changing the comment delimiters - -@cindex changing comment delimiters -@cindex comment delimiters, changing -@cindex delimiters, changing -The default comment delimiters can be changed with the builtin -macro @code{changecom}: - -@deffn {Builtin (m4)} changecom (@ovar{start}, @dvar{end, @key{NL}}) -This sets @var{start} as the new begin-comment delimiter and @var{end} -as the new end-comment delimiter. If both arguments are missing, or -@var{start} is void, then comments are disabled. Otherwise, if -@var{end} is missing or void, the default end-comment delimiter of -newline is used. The comment delimiters can be of any length. - -The expansion of @code{changecom} is void. -@end deffn - -@example -define(`comment', `COMMENT') -@result{} -# A normal comment -@result{}# A normal comment -changecom(`/*', `*/') -@result{} -# Not a comment anymore -@result{}# Not a COMMENT anymore -But: /* this is a comment now */ while this is not a comment -@result{}But: /* this is a comment now */ while this is not a COMMENT -@end example - -@cindex comments, copied to output -Note how comments are copied to the output, much as if they were quoted -strings. If you want the text inside a comment expanded, quote the -begin-comment delimiter. - -Calling @code{changecom} without any arguments, or with @var{start} as -the empty string, will effectively disable the commenting mechanism. To -restore the original comment start of @samp{#}, you must explicitly ask -for it. If @var{start} is not empty, then an empty @var{end} will use -the default end-comment delimiter of newline, as otherwise, it would be -impossible to end a comment. However, this is not portable, as some -other @code{m4} implementations preserve the previous non-empty -delimiters instead. - -@example -define(`comment', `COMMENT') -@result{} -changecom -@result{} -# Not a comment anymore -@result{}# Not a COMMENT anymore -changecom(`#', `') -@result{} -# comment again -@result{}# comment again -@end example - -The comment strings can safely contain eight-bit characters. -If no single character is appropriate, @var{start} and @var{end} can be -of any length. Other implementations cap the delimiter length to five -characters, but GNU has no inherent limit. - -As of M4 1.6, macros and quotes are recognized in preference to -comments, so if a prefix of @var{start} can be recognized as part of a -potential macro name, or confused with a quoted string, the comment -mechanism is effectively disabled (earlier versions of GNU M4 -favored comments, but this was inconsistent with other implementations). -Unless you use @code{changesyntax} (@pxref{Changesyntax}), this means -that @var{start} should not begin with a letter, digit, or @samp{_} -(underscore), and that neither the start-quote nor the start-comment -string should be a prefix of the other. - -@example -define(`hi', `HI') -@result{} -define(`hi1hi2', `hello') -@result{} -changecom(`q', `Q') -@result{} -q hi Q hi -@result{}q HI Q HI -changecom(`1', `2') -@result{} -hi1hi2 -@result{}hello -hi 1hi2 -@result{}HI 1hi2 -changecom(`[[', `]]') -@result{} -changequote(`[[[', `]]]') -@result{} -[hi] -@result{}[HI] -[[hi]] -@result{}[[hi]] -[[[hi]]] -@result{}hi -changequote -@result{} -changecom(`[[[', `]]]') -@result{} -changequote(`[[', `]]') -@result{} -[[hi]] -@result{}hi -[[[hi]]] -@result{}[hi] -@end example - -Comments are recognized in preference to argument collection. In -particular, if @var{start} is a single @samp{(}, then argument -collection is effectively disabled. For portability with other -implementations, it is a good idea to avoid @samp{(}, @samp{,}, and -@samp{)} as the first character in @var{start}. - -@example -define(`echo', `$#:$*:$@@:') -@result{} -define(`hi', `HI') -@result{} -changecom(`(',`)') -@result{} -echo(hi) -@result{}0:::(hi) -changecom -@result{} -changecom(`((', `))') -@result{} -echo(hi) -@result{}1:HI:HI: -echo((hi)) -@result{}0:::((hi)) -changecom(`,', `)') -@result{} -echo(hi,hi)bye) -@result{}1:HI,hi)bye:HI,hi)bye: -changecom -@result{} -echo(hi,`,`'hi',hi) -@result{}3:HI,,HI,HI:HI,,`'hi,HI: -echo(hi,`,`'hi',hi`'changecom(`,,', `hi')) -@result{}3:HI,,`'hi,HI:HI,,`'hi,HI: -@end example - -It is an error if the end of file occurs within a comment. - -@comment status: 1 -@example -changecom(`/*', `*/') -@result{} -/*dangling comment -^D -@error{}m4:stdin:2: end of file in comment -@end example - -@comment status: 1 -@example -changecom(`/*', `*/') -@result{} -len(/*dangling comment -^D -@error{}m4:stdin:2: len: end of file in comment -@end example - -@node Changeresyntax -@section Changing the regular expression syntax - -@cindex regular expression syntax, changing -@cindex basic regular expressions -@cindex extended regular expressions -@cindex regular expressions -@cindex expressions, regular -@cindex syntax, changing regular expression -@cindex flavors of regular expressions -@cindex GNU extensions -The GNU extensions @code{patsubst}, @code{regexp}, and more -recently, @code{renamesyms} each deal with regular expressions. There -are multiple flavors of regular expressions, so the -@code{changeresyntax} builtin exists to allow choosing the default -flavor: - -@deffn {Builtin (gnu)} changeresyntax (@var{resyntax}) -Changes the default regular expression syntax used by M4 according to -the value of @var{resyntax}, equivalent to passing @var{resyntax} as the -argument to the command line option @option{--regexp-syntax} -(@pxref{Operation modes, , Invoking m4}). If @var{resyntax} is empty, -the default flavor is reverted to the @code{GNU_M4} style, compatible -with emacs. - -@var{resyntax} can be any one of the values in the table below. Case is -not important, and @samp{-} or @samp{ } can be substituted for @samp{_} in -the given names. If @var{resyntax} is unrecognized, a warning is -issued and the default flavor is not changed. - -@table @dfn -@item AWK -@xref{awk regular expression syntax}, for details. - -@item BASIC -@itemx ED -@itemx POSIX_BASIC -@itemx SED -@xref{posix-basic regular expression syntax}, for details. - -@item BSD_M4 -@item EXTENDED -@itemx POSIX_EXTENDED -@xref{posix-extended regular expression syntax}, for details. - -@item GNU_AWK -@itemx GAWK -@xref{gnu-awk regular expression syntax}, for details. - -@item GNU_EGREP -@itemx EGREP -@xref{egrep regular expression syntax}, for details. - -@item GNU_M4 -@item EMACS -@itemx GNU_EMACS -@xref{emacs regular expression syntax}, for details. This is the -default regular expression flavor. - -@item GREP -@xref{grep regular expression syntax}, for details. - -@item MINIMAL -@itemx POSIX_MINIMAL -@itemx POSIX_MINIMAL_BASIC -@xref{posix-minimal-basic regular expression syntax}, for details. - -@item POSIX_AWK -@xref{posix-awk regular expression syntax}, for details. - -@item POSIX_EGREP -@xref{posix-egrep regular expression syntax}, for details. -@end table - -The expansion of @code{changeresyntax} is void. -The macro @code{changeresyntax} is recognized only with parameters. -This macro was added in M4 2.0. -@end deffn - -For an example of how @var{resyntax} is recognized, the first three -usages select the @samp{GNU_M4} regular expression flavor: - -@example -changeresyntax(`gnu m4') -@result{} -changeresyntax(`GNU-m4') -@result{} -changeresyntax(`Gnu_M4') -@result{} -changeresyntax(`unknown') -@error{}m4:stdin:4: warning: changeresyntax: bad syntax-spec: 'unknown' -@result{} -@end example - -Using @code{changeresyntax} makes it possible to omit the optional -@var{resyntax} parameter to other macros, while still using a different -regular expression flavor. - -@example -patsubst(`ab', `a|b', `c') -@result{}ab -patsubst(`ab', `a\|b', `c') -@result{}cc -patsubst(`ab', `a|b', `c', `EXTENDED') -@result{}cc -changeresyntax(`EXTENDED') -@result{} -patsubst(`ab', `a|b', `c') -@result{}cc -patsubst(`ab', `a\|b', `c') -@result{}ab -@end example - -@node Changesyntax -@section Changing the lexical structure of the input - -@cindex lexical structure of the input -@cindex input, lexical structure of the -@cindex syntax table -@cindex changing syntax -@cindex GNU extensions -@quotation -The macro @code{changesyntax} and all associated functionality is -experimental (@pxref{Experiments}). The functionality might change in -the future. Please direct your comments about it the same way you would -do for bugs. -@end quotation - -The input to @code{m4} is read character by character, and these -characters are grouped together to form input tokens (such as macro -names, strings, comments, etc.). - -Each token is parsed according to certain rules. For example, a macro -name starts with a letter or @samp{_} and consists of the longest -possible string of letters, @samp{_} and digits. But who is to decide -what characters are letters, digits, quotes, white space? Earlier the -operating system decided, now you do. The builtin macro -@code{changesyntax} is used to change the way @code{m4} parses the input -stream into tokens. - -@deffn {Builtin (gnu)} changesyntax (@var{syntax-spec}, @dots{}) -Each @var{syntax-spec} is a two-part string. The first part is a -command, consisting of a single character describing a syntax category, -and an optional one-character action. The action can be @samp{-} to -remove the listed characters from that category, @samp{=} to set the -category to the listed characters -and reassign all other characters previously in that category to -`Other', or @samp{+} to add the listed characters to the category -without affecting other characters. If an action is not specified, but -additional characters are present, then @samp{=} is assumed. - -The remaining characters of each @var{syntax-spec} form the set of -characters to perform the action on for that syntax category. Character -ranges are expanded as for @code{translit} (@pxref{Translit}). To start -the character set with @samp{-}, @samp{+}, or @samp{=}, an action must -be specified. - -If @var{syntax-spec} is just a category, and no action or characters -were specified, then all characters in that category are reset to their -default state. A warning is issued if the category character is not -valid. If @var{syntax-spec} is the empty string, then all categories -are reset to their default state. - -Syntax categories are divided into basic and context. Every input -byte belongs to exactly one basic syntax category. Additionally, any -byte can be assigned to a context category regardless of its current -basic category. Context categories exist because a character can -behave differently when parsed in isolation than when it occurs in -context to close out a token started by another basic category (for -example, @kbd{newline} defaults to the basic category `Whitespace' as -well as the context category `End comment'). - -The following table describes the case-insensitive designation for each -syntax category (the first byte in @var{syntax-spec}), and a description -of what each category controls. - -@multitable @columnfractions .06 .20 .13 .55 -@headitem Code @tab Category @tab Type @tab Description - -@item @kbd{W} @tab @dfn{Words} @tab Basic -@tab Characters that can start a macro name. Defaults to the letters as -defined by the locale, and the character @samp{_}. - -@item @kbd{D} @tab @dfn{Digits} @tab Basic -@tab Characters that, together with the letters, form the remainder of a -macro name. Defaults to the ten digits @samp{0}@dots{}@samp{9}, and any -other digits defined by the locale. - -@item @kbd{S} @tab @dfn{White space} @tab Basic -@tab Characters that should be trimmed from the beginning of each argument to -a macro call. The defaults are space, tab, newline, carriage return, -form feed, and vertical tab, and any others as defined by the locale. - -@item @kbd{(} @tab @dfn{Open parenthesis} @tab Basic -@tab Characters that open the argument list of a macro call. The default is -the single character @samp{(}. - -@item @kbd{)} @tab @dfn{Close parenthesis} @tab Basic -@tab Characters that close the argument list of a macro call. The default -is the single character @samp{)}. - -@item @kbd{,} @tab @dfn{Argument separator} @tab Basic -@tab Characters that separate the arguments of a macro call. The default is -the single character @samp{,}. - -@item @kbd{L} @tab @dfn{Left quote} @tab Basic -@tab The set of characters that can start a single-character quoted string. -The default is the single character @samp{`}. For multiple-character -quote delimiters, use @code{changequote} (@pxref{Changequote}). - -@item @kbd{R} @tab @dfn{Right quote} @tab Context -@tab The set of characters that can end a single-character quoted string. -The default is the single character @samp{'}. For multiple-character -quote delimiters, use @code{changequote} (@pxref{Changequote}). Note -that @samp{'} also defaults to the syntax category `Other', when it -appears in isolation. - -@item @kbd{B} @tab @dfn{Begin comment} @tab Basic -@tab The set of characters that can start a single-character comment. The -default is the single character @samp{#}. For multiple-character -comment delimiters, use @code{changecom} (@pxref{Changecom}). - -@item @kbd{E} @tab @dfn{End comment} @tab Context -@tab The set of characters that can end a single-character comment. The -default is the single character @kbd{newline}. For multiple-character -comment delimiters, use @code{changecom} (@pxref{Changecom}). Note that -newline also defaults to the syntax category `White space', when it -appears in isolation. - -@item @kbd{$} @tab @dfn{Dollar} @tab Context -@tab Characters that can introduce an argument reference in the body of a -macro. The default is the single character @samp{$}. - -@comment FIXME - implement ${10} argument parsing. -@item @kbd{@{} @tab @dfn{Left brace} @tab Context -@tab Characters that introduce an extended argument reference in the body of -a macro immediately after a character in the Dollar category. The -default is the single character @samp{@{}. - -@item @kbd{@}} @tab @dfn{Right brace} @tab Context -@tab Characters that conclude an extended argument reference in the body of a -macro. The default is the single character @samp{@}}. - -@item @kbd{O} @tab @dfn{Other} @tab Basic -@tab Characters that have no special syntactical meaning to @code{m4}. -Defaults to all characters except those in the categories above. - -@item @kbd{A} @tab @dfn{Active} @tab Basic -@tab Characters that themselves, alone, form macro names. This is a -GNU extension, and active characters have lower precedence -than comments. By default, no characters are active. - -@item @kbd{@@} @tab @dfn{Escape} @tab Basic -@tab Characters that must precede macro names for them to be recognized. -This is a GNU extension. When an escape character is defined, -then macros are not recognized unless the escape character is present; -however, the macro name, visible by @samp{$0} in macro definitions, does -not include the escape character. By default, no characters are -escapes. - -@comment FIXME - we should also consider supporting: -@comment @item @kbd{I} @tab @dfn{Ignore} @tab Basic -@comment @tab Characters that are ignored if they appear in -@comment the input; perhaps defaulting to '\0'. -@end multitable - -The expansion of @code{changesyntax} is void. -The macro @code{changesyntax} is recognized only with parameters. Use -this macro with caution, as it is possible to change the syntax in such -a way that no further macros can be recognized by @code{m4}. -This macro was added in M4 2.0. -@end deffn - -With @code{changesyntax} we can modify what characters form a word. For -example, we can make @samp{.} a valid character in a macro name, or even -start a macro name with a number. - -@example -define(`test.1', `TEST ONE') -@result{} -define(`1', `one') -@result{} -__file__ -@result{}stdin -test.1 -@result{}test.1 -dnl Add `.' and remove `_'. -changesyntax(`W+.', `W-_') -@result{} -__file__ -@result{}__file__ -test.1 -@result{}TEST ONE -dnl Set words to include numbers. -changesyntax(`W=a-zA-Z0-9_') -@result{} -__file__ -@result{}stdin -test.1 -@result{}test.one -dnl Reset words to default (a-zA-Z_). -changesyntax(`W') -@result{} -__file__ -@result{}stdin -test.1 -@result{}test.1 -@end example - -Another possibility is to change the syntax of a macro call. - -@example -define(`test', `$#') -@result{} -test(a, b, c) -@result{}3 -dnl Change macro syntax. -changesyntax(`(<', `,|', `)>') -@result{} -test(a, b, c) -@result{}0(a, b, c) -test -@result{}3 -@end example - -Leading spaces are always removed from macro arguments in @code{m4}, but -by changing the syntax categories we can avoid it. The use of -@code{format} is an alternative to using a literal tab character. - -@example -define(`test', `$1$2$3') -@result{} -test(`a', `b', `c') -@result{}abc -dnl Don't ignore whitespace. -changesyntax(`O 'format(``%c'', `9')` -') -@result{} -test(a, b, -c) -@result{}a b -@result{}c -@end example - -It is possible to redefine the @samp{$} used to indicate macro arguments -in user defined macros. Dollar class syntax elements are copied to the -output if there is no valid expansion. - -@example -define(`argref', `Dollar: $#, Question: ?#') -@result{} -argref(1, 2, 3) -@result{}Dollar: 3, Question: ?# -dnl Change argument identifier. -changesyntax(`$?') -@result{} -argref(1,2,3) -@result{}Dollar: $#, Question: 3 -define(`escape', `$?`'1$?1?') -@result{} -escape(foo) -@result{}$?1$foo? -dnl Multiple argument identifiers. -changesyntax(`$+$') -@result{} -argref(1, 2, 3) -@result{}Dollar: 3, Question: 3 -@end example - -Macro calls can be given a @TeX{} or Texinfo like syntax using an -escape. If one or more characters are defined as escapes, macro names -are only recognized if preceded by an escape character. - -If the escape is not followed by what is normally a word (a letter -optionally followed by letters and/or numerals), that single character -is returned as a macro name. - -As always, words without a macro definition cause no error message. -They and the escape character are simply output. - -@example -define(`foo', `bar') -@result{} -dnl Require @@ escape before any macro. -changesyntax(`@@@@') -@result{} -foo -@result{}foo -@@foo -@result{}bar -@@bar -@result{}@@bar -@@dnl Change escape character. -@@changesyntax(`@@\', `O@@') -@result{} -foo -@result{}foo -@@foo -@result{}@@foo -\foo -@result{}bar -define(`#', `No comment') -@result{}define(#, No comment) -\define(`#', `No comment') -@result{} -\# \foo # Comment \foo -@result{}No comment bar # Comment \foo -@end example - -Active characters are known from @TeX{}. In @code{m4} an active -character is always seen as a one-letter word, and so, if it has a macro -definition, the macro will be called. - -@example -define(`@@', `TEST') -@result{} -define(`a@@a', `hello') -@result{} -define(`a', `A') -@result{} -@@ -@result{}@@ -a@@a -@result{}A@@A -dnl Make @@ active. -changesyntax(`A@@') -@result{} -@@ -@result{}TEST -a@@a -@result{}ATESTa -@end example - -There is obviously an overlap between @code{changesyntax} and -@code{changequote}, since there are now two ways to modify quote -delimiters. To avoid incompatibilities, if the quotes are modified by -@code{changequote}, any characters previously set to either quote -delimiter by @code{changesyntax} are first demoted to the other category -(@samp{O}), so the result is only a single set of quotes. In the other -direction, if quotes were already disabled, or if both the start and end -delimiter set by @code{changequote} are single bytes, then -@code{changesyntax} preserves those settings. But if either delimiter -occupies multiple bytes, @code{changesyntax} first disables both -delimiters. Quotes can be disabled via @code{changesyntax} by emptying -the left quote basic category (@samp{L}). Meanwhile, the right quote -context category (@samp{R}) will never be empty; if a -@code{changesyntax} action would otherwise leave that category empty, -then the default end delimiter from @code{changequote} (@samp{'}) is -used; thus, it is never possible to get @code{m4} in a state where a -quoted string cannot be terminated. These interactions apply to comment -delimiters as well, @i{mutatis mutandis} with @code{changecom}. - -@example -define(`test', `TEST') -@result{} -dnl Add additional single-byte delimiters. -changesyntax(`L+<', `R+>') -@result{} - `test' [test] <> -@result{}test test [TEST] -dnl Use standard interface, overriding changesyntax settings. -changequote(<[>, `]') -@result{} - `test' [test] <> -@result{} `TEST' test <> -dnl Introduce multi-byte delimiters. -changequote([<<], [>>]) -@result{} - `test' [test] <> -@result{} `TEST' [TEST] test -dnl Change end quote, effectively disabling quotes. -changesyntax(<>) -@result{} - `test' [test] <> -@result{} `TEST' [TEST] <> -dnl Change beginning quote, make ] normal, thus making ' end quote. -changesyntax(L`, R-]) -@result{} - `test' [test] <> -@result{} test [TEST] <> -dnl Set multi-byte quote; unrelated changes don't impact it. -changequote(`<<', `>>')changesyntax(<<@@\>>) -@result{} -<\test> `\test' [\test] <<\test>> -@result{} `TEST' [TEST] \test -@end example - -If several characters are assigned to a category that forms single -character tokens, all such characters are treated as equal. Any open -parenthesis will match any close parenthesis, etc. - -@example -dnl Go crazy with symbols. -changesyntax(`(@{<', `)@}>', `,;:', `O(,)') -@result{} -eval@{2**4-1; 2: 8> -@result{}00001111 -@end example - -The syntax table is initialized to be backwards compatible, so if you -never call @code{changesyntax}, nothing will have changed. - -For now, debugging output continues to use @kbd{(}, @kbd{,} and @kbd{)} -to show macro calls; and macro expansions that result in a list of -arguments (such as @samp{$@@} or @code{shift}) use @samp{,}, regardless -of the current syntax settings. However, this is likely to change in a -future release, so it should not be relied on, particularly since it is -next to impossible to write recursive macros if the argument separator -doesn't match between expansion and rescanning. - -@c FIXME - changing syntax of , should not break iterative macros. -@example -$ @kbd{m4 -d} -changesyntax(`,=|')traceon(`foo')define(`foo'|`$#:$@@') -@result{} -foo(foo(1|2|3)) -@error{}m4trace: -2- foo(`1', `2', `3') -> `3:`1',`2',`3'' -@error{}m4trace: -1- foo(`3:1,2,3') -> `1:`3:1,2,3'' -@result{}1:3:1,2,3 -@end example - -@node M4wrap -@section Saving text until end of input - -@cindex saving input -@cindex input, saving -@cindex deferring expansion -@cindex expansion, deferring -It is possible to `save' some text until the end of the normal input has -been seen. Text can be saved, to be read again by @code{m4} when the -normal input has been exhausted. This feature is normally used to -initiate cleanup actions before normal exit, e.g., deleting temporary -files. - -To save input text, use the builtin @code{m4wrap}: - -@deffn {Builtin (m4)} m4wrap (@var{string}, @dots{}) -Stores @var{string} in a safe place, to be reread when end of input is -reached. As a GNU extension, additional arguments are -concatenated with a space to the @var{string}. - -Successive invocations of @code{m4wrap} accumulate saved text in -first-in, first-out order, as required by POSIX. - -The expansion of @code{m4wrap} is void. -The macro @code{m4wrap} is recognized only with parameters. -@end deffn - -@example -define(`cleanup', `This is the `cleanup' action. -') -@result{} -m4wrap(`cleanup') -@result{} -This is the first and last normal input line. -@result{}This is the first and last normal input line. -^D -@result{}This is the cleanup action. -@end example - -The saved input is only reread when the end of normal input is seen, and -not if @code{m4exit} is used to exit @code{m4}. - -It is safe to call @code{m4wrap} from wrapped text, where all the -recursively wrapped text is deferred until the current wrapped text is -exhausted. As of M4 1.6, when @code{m4wrap} is not used recursively, -the saved pieces of text are reread in the same order in which they were -saved (FIFO---first in, first out), as required by POSIX. - -@example -m4wrap(`1 -') -@result{} -m4wrap(`2', `3 -') -@result{} -^D -@result{}1 -@result{}2 3 -@end example - -However, earlier versions had reverse ordering (LIFO---last in, first -out), as this behavior is more like the semantics of the C function -@code{atexit}. It is possible to emulate POSIX behavior even -with older versions of GNU M4 by including the file -@file{m4-@value{VERSION}/@/doc/examples/@/wrapfifo.m4} from the -distribution: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -undivert(`wrapfifo.m4')dnl -@result{}dnl Redefine m4wrap to have FIFO semantics. -@result{}define(`_m4wrap_level', `0')dnl -@result{}define(`m4wrap', -@result{}`ifdef(`m4wrap'_m4wrap_level, -@result{} `define(`m4wrap'_m4wrap_level, -@result{} defn(`m4wrap'_m4wrap_level)`$1')', -@result{} `builtin(`m4wrap', `define(`_m4wrap_level', -@result{} incr(_m4wrap_level))dnl -@result{}m4wrap'_m4wrap_level)dnl -@result{}define(`m4wrap'_m4wrap_level, `$1')')')dnl -include(`wrapfifo.m4') -@result{} -m4wrap(`a`'m4wrap(`c -', `d')')m4wrap(`b') -@result{} -^D -@result{}abc -@end example - -It is likewise possible to emulate LIFO behavior without resorting to -the GNU M4 extension of @code{builtin}, by including the file -@file{m4-@value{VERSION}/@/doc/examples/@/wraplifo.m4} from the -distribution. (Unfortunately, both examples shown here share some -subtle bugs. See if you can find and correct them; or @pxref{Improved -m4wrap, , Answers}). - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -undivert(`wraplifo.m4')dnl -@result{}dnl Redefine m4wrap to have LIFO semantics. -@result{}define(`_m4wrap_level', `0')dnl -@result{}define(`_m4wrap', defn(`m4wrap'))dnl -@result{}define(`m4wrap', -@result{}`ifdef(`m4wrap'_m4wrap_level, -@result{} `define(`m4wrap'_m4wrap_level, -@result{} `$1'defn(`m4wrap'_m4wrap_level))', -@result{} `_m4wrap(`define(`_m4wrap_level', incr(_m4wrap_level))dnl -@result{}m4wrap'_m4wrap_level)dnl -@result{}define(`m4wrap'_m4wrap_level, `$1')')')dnl -include(`wraplifo.m4') -@result{} -m4wrap(`a`'m4wrap(`c -', `d')')m4wrap(`b') -@result{} -^D -@result{}bac -@end example - -Here is an example of implementing a factorial function using -@code{m4wrap}: - -@example -define(`f', `ifelse(`$1', `0', `Answer: 0!=1 -', eval(`$1>1'), `0', `Answer: $2$1=eval(`$2$1') -', `m4wrap(`f(decr(`$1'), `$2$1*')')')') -@result{} -f(`10') -@result{} -^D -@result{}Answer: 10*9*8*7*6*5*4*3*2*1=3628800 -@end example - -Invocations of @code{m4wrap} at the same recursion level are -concatenated and rescanned as usual: - -@example -define(`ab', `AB -') -@result{} -m4wrap(`a')m4wrap(`b') -@result{} -^D -@result{}AB -@end example - -@noindent -however, the transition between recursion levels behaves like an end of -file condition between two input files. - -@comment status: 1 -@example -m4wrap(`m4wrap(`)')len(abc') -@result{} -^D -@error{}m4:stdin:1: len: end of file in argument list -@end example - -As of M4 1.6, @code{m4wrap} transparently handles builtin tokens -generated by @code{defn} (@pxref{Defn}). However, for portability, it -is better to defer the evaluation of @code{defn} along with the rest of -the wrapped text, as is done for @code{foo} in the example below, rather -than computing the builtin token up front, as is done for @code{bar}. - -@example -m4wrap(`define(`foo', defn(`divnum'))foo -') -@result{} -m4wrap(`define(`bar', ')m4wrap(defn(`divnum'))m4wrap(`)bar -') -@result{} -^D -@result{}0 -@result{}0 -@end example - -@node File Inclusion -@chapter File inclusion - -@cindex file inclusion -@cindex inclusion, of files -@code{m4} allows you to include named files at any point in the input. - -@menu -* Include:: Including named files and modules -* Search Path:: Searching for include files -@end menu - -@node Include -@section Including named files and modules - -There are two builtin macros in @code{m4} for including files: - -@deffn {Builtin (m4)} include (@var{file}) -@deffnx {Builtin (m4)} sinclude (@var{file}) -Both macros cause the file named @var{file} to be read by -@code{m4}. When the end of the file is reached, input is resumed from -the previous input file. - -The expansion of @code{include} and @code{sinclude} is therefore the -contents of @var{file}. - -If @var{file} does not exist, is a directory, or cannot otherwise be -read, the expansion is void, -and @code{include} will fail with an error while @code{sinclude} is -silent. The empty string counts as a file that does not exist. - -The macros @code{include} and @code{sinclude} are recognized only with -parameters. -@end deffn - -@comment status: 1 -@example -include(`n') -@error{}m4:stdin:1: include: cannot open file 'n': No such file or directory -@result{} -include() -@error{}m4:stdin:2: include: cannot open file '': No such file or directory -@result{} -sinclude(`n') -@result{} -sinclude() -@result{} -@end example - -This section uses the @option{--include} command-line option (or -@option{-I}, @pxref{Preprocessor features, , Invoking m4}) to grab -files from the @file{m4-@value{VERSION}/@/doc/examples} -directory shipped as part of the GNU @code{m4} package. The -file @file{m4-@value{VERSION}/@/doc/examples/@/incl.m4} in the distribution -contains the lines: - -@comment ignore -@example -$ @kbd{cat doc/examples/incl.m4} -@result{}Include file start -@result{}foo -@result{}Include file end -@end example - -Normally file inclusion is used to insert the contents of a file -into the input stream. The contents of the file will be read by -@code{m4} and macro calls in the file will be expanded: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -define(`foo', `FOO') -@result{} -include(`incl.m4') -@result{}Include file start -@result{}FOO -@result{}Include file end -@result{} -@end example - -The fact that @code{include} and @code{sinclude} expand to the contents -of the file can be used to define macros that operate on entire files. -Here is an example, which defines @samp{bar} to expand to the contents -of @file{incl.m4}: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -define(`bar', include(`incl.m4')) -@result{} -This is `bar': >>bar<< -@result{}This is bar: >>Include file start -@result{}foo -@result{}Include file end -@result{}<< -@end example - -This use of @code{include} is not trivial, though, as files can contain -quotes, commas, and parentheses, which can interfere with the way the -@code{m4} parser works. GNU M4 seamlessly concatenates -the file contents with the next character, even if the included file -ended in the middle of a comment, string, or macro call. These -conditions are only treated as end of file errors if specified as input -files on the command line. - -In GNU M4, an alternative method of reading files is -using @code{undivert} (@pxref{Undivert}) on a named file. - -In addition, as a GNU M4 extension, if the included file cannot -be found exactly as given, various standard suffixes are appended. -If the included file name is absolute (a full path from the root directory -is given) then additional search directories are not examined, although -suffixes will be tried if the file is not found exactly as given. -For each directory that is searched (according to the absolute directory -give in the file name, or else by directories listed in @env{M4PATH} and -given with the @option{-I} and @option{-B} options), first the unchanged -file name is tried, and then again with the suffixes @samp{.m4f} and -@samp{.m4}. - -Furthermore, if no matching file has yet been found, before moving on to -the next directory, @samp{.la} and the usual binary module suffix for -the host platform (usually @samp{.so}) are also tried. Matching with one -of those suffixes will attempt to load the matched file as a dynamic -module. @xref{Modules}, for more details. - -@node Search Path -@section Searching for include files - -@cindex search path for included files -@cindex included files, search path for -@cindex GNU extensions -GNU @code{m4} allows included files to be found in other directories -than the current working directory. - -@cindex @env{M4PATH} -If the @option{--prepend-include} or @option{-B} command-line option was -provided (@pxref{Preprocessor features, , Invoking m4}), those -directories are searched first, in reverse order that those options were -listed on the command line. Then @code{m4} looks in the current working -directory. Next comes the directories specified with the -@option{--include} or @option{-I} option, in the order found on the -command line. Finally, if the @env{M4PATH} environment variable is set, -it is expected to contain a colon-separated list of directories, which -will be searched in order. - -If the automatic search for include-files causes trouble, the @samp{p} -debug flag (@pxref{Debugmode}) can help isolate the problem. - -@node Diversions -@chapter Diverting and undiverting output - -@cindex deferring output -Diversions are a way of temporarily saving output. The output of -@code{m4} can at any time be diverted to a temporary file, and be -reinserted into the output stream, @dfn{undiverted}, again at a later -time. - -@cindex @env{TMPDIR} -Numbered diversions are counted from 0 upwards, diversion number 0 -being the normal output stream. GNU -@code{m4} tries to keep diversions in memory. However, there is a -limit to the overall memory usable by all diversions taken together -(512K, currently). When this maximum is about to be exceeded, -a temporary file is opened to receive the contents of the biggest -diversion still in memory, freeing this memory for other diversions. -When creating the temporary file, @code{m4} honors the value of the -environment variable @env{TMPDIR}, and falls back to @file{/tmp}. -Thus, the amount of available disk space provides the only real limit on -the number and aggregate size of diversions. - -Diversions make it possible to generate output in a different order than -the input was read. It is possible to implement topological sorting -dependencies. For example, GNU Autoconf makes use of -diversions under the hood to ensure that the expansion of a prerequisite -macro appears in the output prior to the expansion of a dependent macro, -regardless of which order the two macros were invoked in the user's -input file. - -@menu -* Divert:: Diverting output -* Undivert:: Undiverting output -* Divnum:: Diversion numbers -* Cleardivert:: Discarding diverted text -@end menu - -@node Divert -@section Diverting output - -@cindex diverting output to files -@cindex output, diverting to files -@cindex files, diverting output to -Output is diverted using @code{divert}: - -@deffn {Builtin (m4)} divert (@dvar{number, 0}, @ovar{text}) -The current diversion is changed to @var{number}. If @var{number} is left -out or empty, it is assumed to be zero. If @var{number} cannot be -parsed, the diversion is unchanged. - -@cindex GNU extensions -As a GNU extension, if optional @var{text} is supplied and -@var{number} was valid, then @var{text} is immediately output to the -new diversion, regardless of whether the expansion of @code{divert} -occurred while collecting arguments for another macro. - -The expansion of @code{divert} is void. -@end deffn - -When all the @code{m4} input will have been processed, all existing -diversions are automatically undiverted, in numerical order. - -@example -divert(`1') -This text is diverted. -divert -@result{} -This text is not diverted. -@result{}This text is not diverted. -^D -@result{} -@result{}This text is diverted. -@end example - -Several calls of @code{divert} with the same argument do not overwrite -the previous diverted text, but append to it. Diversions are printed -after any wrapped text is expanded. - -@example -define(`text', `TEXT') -@result{} -divert(`1')`diverted text.' -divert -@result{} -m4wrap(`Wrapped text precedes ') -@result{} -^D -@result{}Wrapped TEXT precedes diverted text. -@end example - -@cindex discarding input -@cindex input, discarding -If output is diverted to a negative diversion, it is simply discarded. -This can be used to suppress unwanted output. A common example of -unwanted output is the trailing newlines after macro definitions. Here -is a common programming idiom in @code{m4} for avoiding them. - -@example -divert(`-1') -define(`foo', `Macro `foo'.') -define(`bar', `Macro `bar'.') -divert -@result{} -@end example - -@cindex GNU extensions -Traditional implementations only supported ten diversions. But as a -GNU extension, diversion numbers can be as large as positive -integers will allow, rather than treating a multi-digit diversion number -as a request to discard text. - -@example -divert(eval(`1<<28'))world -divert(`2')hello -^D -@result{}hello -@result{}world -@end example - -The ability to immediately output extra text is a GNU -extension, but it can prove useful for ensuring that text goes to a -particular diversion no matter how many pending macro expansions are in -progress. For a demonstration of why this is useful, it is important to -understand in the example below why @samp{one} is output in diversion 2, -not diversion 1, while @samp{three} and @samp{five} both end up in the -correctly numbered diversion. The key point is that when @code{divert} -is executed unquoted as part of the argument collection of another -macro, the side effect takes place immediately, but the text @samp{one} -is not passed to any diversion until after the @samp{divert(`2')} and -the enclosing @code{echo} have also taken place. The example with -@samp{three} shows how following the quoting rule of thumb delays the -invocation of @code{divert} until it is not nested in any argument -collection context, while the example with @samp{five} shows the use of -the optional argument to speed up the output process. - -@example -define(`echo', `$1') -@result{} -echo(divert(`1')`one'divert(`2'))`'dnl -echo(`divert(`3')three`'divert(`4')')`'dnl -echo(divert(`5', `five')divert(`6'))`'dnl -divert -@result{} -undivert(`1') -@result{} -undivert(`2') -@result{}one -undivert(`3') -@result{}three -undivert(`4') -@result{} -undivert(`5') -@result{}five -undivert(`6') -@result{} -@end example - -Note that @code{divert} is an English word, but also an active macro -without arguments. When processing plain text, the word might appear in -normal text and be unintentionally swallowed as a macro invocation. One -way to avoid this is to use the @option{-P} option to rename all -builtins (@pxref{Operation modes, , Invoking m4}). Another is to write -a wrapper that requires a parameter to be recognized. - -@example -We decided to divert the stream for irrigation. -@result{}We decided to the stream for irrigation. -define(`divert', `ifelse(`$#', `0', ``$0'', `builtin(`$0', $@@)')') -@result{} -divert(`-1') -Ignored text. -divert(`0') -@result{} -We decided to divert the stream for irrigation. -@result{}We decided to divert the stream for irrigation. -@end example - -@node Undivert -@section Undiverting output - -Diverted text can be undiverted explicitly using the builtin -@code{undivert}: - -@deffn {Builtin (m4)} undivert (@ovar{diversions@dots{}}) -Undiverts the numeric @var{diversions} given by the arguments, in the -order given. If no arguments are supplied, all diversions are -undiverted, in numerical order. - -@cindex file inclusion -@cindex inclusion, of files -@cindex GNU extensions -As a GNU extension, @var{diversions} may contain non-numeric -strings, which are treated as the names of files to copy into the output -without expansion. A warning is issued if a file could not be opened. - -The expansion of @code{undivert} is void. -@end deffn - -@example -divert(`1') -This text is diverted. -divert -@result{} -This text is not diverted. -@result{}This text is not diverted. -undivert(`1') -@result{} -@result{}This text is diverted. -@result{} -@end example - -Notice the last two blank lines. One of them comes from the newline -following @code{undivert}, the other from the newline that followed the -@code{divert}! A diversion often starts with a blank line like this. - -When diverted text is undiverted, it is @emph{not} reread by @code{m4}, -but rather copied directly to the current output, and it is therefore -not an error to undivert into a diversion. Undiverting the empty string -is the same as specifying diversion 0; in either case nothing happens -since the output has already been flushed. - -@example -divert(`1')diverted text -divert -@result{} -undivert() -@result{} -undivert(`0') -@result{} -undivert -@result{}diverted text -@result{} -divert(`1')more -divert(`2')undivert(`1')diverted text`'divert -@result{} -undivert(`1') -@result{} -undivert(`2') -@result{}more -@result{}diverted text -@end example - -When a diversion has been undiverted, the diverted text is discarded, -and it is not possible to bring back diverted text more than once. - -@example -divert(`1') -This text is diverted first. -divert(`0')undivert(`1')dnl -@result{} -@result{}This text is diverted first. -undivert(`1') -@result{} -divert(`1') -This text is also diverted but not appended. -divert(`0')undivert(`1')dnl -@result{} -@result{}This text is also diverted but not appended. -@end example - -Attempts to undivert the current diversion are silently ignored. Thus, -when the current diversion is not 0, the current diversion does not get -rearranged among the other diversions. - -@example -divert(`1')one -divert(`2')two -divert(`3')three -divert(`4')four -divert(`5')five -divert(`2')undivert(`5', `2', `4')dnl -undivert`'dnl effectively undivert(`1', `2', `3', `4', `5') -divert`'undivert`'dnl -@result{}two -@result{}five -@result{}four -@result{}one -@result{}three -@end example - -@cindex GNU extensions -@cindex file inclusion -@cindex inclusion, of files -GNU @code{m4} allows named files to be undiverted. Given a -non-numeric argument, the contents of the file named will be copied, -uninterpreted, to the current output. This complements the builtin -@code{include} (@pxref{Include}). To illustrate the difference, assume -the file @file{foo} contains: - -@comment file: foo -@example -$ @kbd{cat foo} -bar -@end example - -@noindent -then - -@example -define(`bar', `BAR') -@result{} -undivert(`foo') -@result{}bar -@result{} -include(`foo') -@result{}BAR -@result{} -@end example - -If the file is not found (or cannot be read), an error message is -issued, and the expansion is void. It is possible to intermix files -and diversion numbers. - -@example -divert(`1')diversion one -divert(`2')undivert(`foo')dnl -divert(`3')diversion three -divert`'dnl -undivert(`1', `2', `foo', `3')dnl -@result{}diversion one -@result{}bar -@result{}bar -@result{}diversion three -@end example - -@node Divnum -@section Diversion numbers - -@cindex diversion numbers -The current diversion is tracked by the builtin @code{divnum}: - -@deffn {Builtin (m4)} divnum -Expands to the number of the current diversion. -@end deffn - -@example -Initial divnum -@result{}Initial 0 -divert(`1') -Diversion one: divnum -divert(`2') -Diversion two: divnum -^D -@result{} -@result{}Diversion one: 1 -@result{} -@result{}Diversion two: 2 -@end example - -@node Cleardivert -@section Discarding diverted text - -@cindex discarding diverted text -@cindex diverted text, discarding -Often it is not known, when output is diverted, whether the diverted -text is actually needed. Since all non-empty diversion are brought back -on the main output stream when the end of input is seen, a method of -discarding a diversion is needed. If all diversions should be -discarded, the easiest is to end the input to @code{m4} with -@samp{divert(`-1')} followed by an explicit @samp{undivert}: - -@example -divert(`1') -Diversion one: divnum -divert(`2') -Diversion two: divnum -divert(`-1') -undivert -^D -@end example - -@noindent -No output is produced at all. - -Clearing selected diversions can be done with the following macro: - -@deffn Composite cleardivert (@ovar{diversions@dots{}}) -Discard the contents of each of the listed numeric @var{diversions}. -@end deffn - -@example -define(`cleardivert', -`pushdef(`_n', divnum)divert(`-1')undivert($@@)divert(_n)popdef(`_n')') -@result{} -@end example - -It is called just like @code{undivert}, but the effect is to clear the -diversions, given by the arguments. (This macro has a nasty bug! You -should try to see if you can find it and correct it; or @pxref{Improved -cleardivert, , Answers}). - -@node Modules -@chapter Extending M4 with dynamic runtime modules - -@cindex modules -@cindex dynamic modules -@cindex loadable modules -GNU M4 1.4.x had a monolithic architecture. All of its -functionality was contained in a single binary, and additional macros -could be added only by writing more code in the M4 language, or at the -extreme by hacking the sources and recompiling the whole thing to make -a custom M4 installation. - -Starting with release 2.0, M4 supports and is composed of loadable modules. -Additional modules can be loaded into the running M4 interpreter as it is -started up at the command line, or during normal expansion of macros. This -facilitates runtime extension of the M4 builtin macro list using compiled C -code linked against a new shared library, typically named @file{libm4.so}. - -For example, you might want to add a @code{setenv} builtin to M4, to -use before invoking @code{esyscmd}. We might write a @file{setenv.c} -something like this: - -@comment ignore -@example -#include "m4module.h" - -M4BUILTIN(setenv); - -m4_builtin m4_builtin_table[] = -@{ - /* name handler flags minargs maxargs */ - @{ "setenv", builtin_setenv, M4_BUILTIN_BLIND, 2, 3 @}, - - @{ NULL, NULL, 0, 0, 0 @} -@}; - -/** - * setenv(NAME, VALUE, [OVERWRITE]) - **/ -M4BUILTIN_HANDLER (setenv) -@{ - int overwrite = 1; - - if (argc >= 4) - if (!m4_numeric_arg (context, argc, argv, 3, &overwrite)) - return; - - setenv (M4ARG (1), M4ARG (2), overwrite); -@} -@end example - -Then, having compiled and linked the module, in (somewhat contrived) -M4 code: - -@comment ignore -@example -$ @kbd{m4 setenv} -setenv(`PATH', `/sbin:/bin:/usr/sbin:/usr/bin') -@result{} -esyscmd(`ifconfig -a')dnl -@result{}@dots{} -@end example - -Or instead of loading the module from the M4 invocation, you can use -the @code{include} builtin: - -@comment ignore -@example -$ @kbd{m4} -include(`setenv') -@result{} -setenv(`PATH', `/sbin:/bin:/usr/sbin:/usr/bin') -@result{} -@end example - -Also, at run time, you can choose which core modules to load. SUSv3 M4 -functionality is contained in the module @samp{m4}, GNU extensions in the -module @samp{gnu}, and so on. All of the builtin descriptions in this manual -are annotated with the module from which they are loaded -- mostly from the -module @samp{m4}. - -When you start GNU M4, the modules @samp{m4} and @samp{gnu} are -loaded by default. If you supply the @option{-G} option at startup, the -module @samp{traditional} is loaded instead of @samp{gnu}. -@xref{Compatibility}, for more details on the differences between these -two modes of startup. - -@menu -* M4modules:: Listing loaded modules -* Standard Modules:: Standard bundled modules -@end menu - -@node M4modules -@section Listing loaded modules - -@deffn {Builtin (gnu)} m4modules -Expands to a quoted ordered list of currently loaded modules, -with the most recently loaded module at the front of the list. Loading -a module multiple times will not affect the order of this list, the -position depends on when the module was @emph{first} loaded. -@end deffn - -For example, after GNU @code{m4} is started with no additional modules, -@code{m4modules} will yield the following: - -@example -$ @kbd{m4} -m4modules -@result{}gnu,m4 -@end example - -@node Standard Modules -@section Standard bundled modules - -GNU @code{m4} ships with several bundled modules as standard. -By convention, these modules define a text macro that can be tested -with @code{ifdef} when they are loaded; only the @code{m4} module lacks -this feature test macro, since it is not permitted by POSIX. -Each of the feature test macros are intended to be used without -arguments. - -@table @code -@item m4 -Provides all of the builtins defined by POSIX. This module -is always loaded --- GNU @code{m4} would only be a very slow -version of @command{cat} without the builtins supplied by this module. - -@item gnu -Provides all of the GNU extensions, as defined by -GNU M4 through the 1.4.x release series. It also provides a -couple of feature test macros: - -@deffn {Macro (gnu)} __gnu__ -Expands to the empty string, as an indication that the @samp{gnu} -module is loaded. -@end deffn - -@deffn {Macro (gnu)} __m4_version__ -Expands to an unquoted string containing the release version number of -the running GNU @code{m4} executable. -@end deffn - -This module is always loaded, unless the @option{-G} command line -option is supplied at startup (@pxref{Limits control, , Invoking m4}). - -@item traditional -This module provides compatibility with System V @code{m4}, for anything -not specified by POSIX, and is loaded instead of the -@samp{gnu} module if the @option{-G} command line option is specified. - -@deffn {Macro (traditional)} __traditional__ -Expands to the empty string, as an indication that the -@samp{traditional} module is loaded. -@end deffn - -@item mpeval -This module provides the implementation for the experimental -@code{mpeval} feature. If the host machine does not have the -GNU gmp library, the builtin will generate an error if called. -@xref{Mpeval}, for more details. The module also defines the following -macro: - -@deffn {Macro (mpeval)} __mpeval__ -Expands to the empty string, as an indication that the @samp{mpeval} -module is loaded. -@end deffn -@end table - -Here is an example of using the feature test macros. - -@example -$ @kbd{m4} -__gnu__-__traditional__ -@result{}-__traditional__ -ifdef(`__gnu__', `Extensions are active', `Minimal features') -@result{}Extensions are active -__gnu__(`ignored') -@error{}m4:stdin:3: warning: __gnu__: extra arguments ignored: 1 > 0 -@result{} -@end example - -@comment options: -G -@example -$ @kbd{m4 --traditional} -__gnu__-__traditional__ -@result{}__gnu__- -ifdef(`__gnu__', `Extensions are active', `Minimal features') -@result{}Minimal features -@end example - -Since the version string is unquoted and can potentially contain macro -names (for example, a beta release could be numbered @samp{1.9b}), or be -impacted by the use of @code{changesyntax}), the -@code{__m4_version__} macro should generally be used via @code{defn} -rather than directly invoked (@pxref{Defn}). In general, feature tests -are more reliable than version number checks, so exercise caution when -using this macro. - -@comment This test is excluded from the testsuite since it depends on a -@comment texinfo macro; but builtins.at covers the same thing. -@comment ignore -@example -defn(`__m4_version__') -@result{}@value{VERSION} -@end example - -@node Text handling -@chapter Macros for text handling - -There are a number of builtins in @code{m4} for manipulating text in -various ways, extracting substrings, searching, substituting, and so on. - -@menu -* Len:: Calculating length of strings -* Index macro:: Searching for substrings -* Regexp:: Searching for regular expressions -* Substr:: Extracting substrings -* Translit:: Translating characters -* Patsubst:: Substituting text by regular expression -* Format:: Formatting strings (printf-like) -@end menu - -@node Len -@section Calculating length of strings - -@cindex length of strings -@cindex strings, length of -The length of a string can be calculated by @code{len}: - -@deffn {Builtin (m4)} len (@var{string}) -Expands to the length of @var{string}, as a decimal number. - -The macro @code{len} is recognized only with parameters. -@end deffn - -@example -len() -@result{}0 -len(`abcdef') -@result{}6 -@end example - -@node Index macro -@section Searching for substrings - -@cindex substrings, locating -Searching for substrings is done with @code{index}: - -@deffn {Builtin (m4)} index (@var{string}, @var{substring}, @ovar{offset}) -Expands to the index of the first occurrence of @var{substring} in -@var{string}. The first character in @var{string} has index 0. If -@var{substring} does not occur in @var{string}, @code{index} expands to -@samp{-1}. If @var{offset} is provided, it determines the index at -which the search starts; a negative @var{offset} specifies the offset -relative to the end of @var{string}. - -The macro @code{index} is recognized only with parameters. -@end deffn - -@example -index(`gnus, gnats, and armadillos', `nat') -@result{}7 -index(`gnus, gnats, and armadillos', `dag') -@result{}-1 -@end example - -Omitting @var{substring} evokes a warning, but still produces output; -contrast this with an empty @var{substring}. - -@example -index(`abc') -@error{}m4:stdin:1: warning: index: too few arguments: 1 < 2 -@result{}0 -index(`abc', `') -@result{}0 -index(`abc', `b') -@result{}1 -@end example - -@cindex GNU extensions -As an extension, an @var{offset} can be provided to limit the search to -the tail of the @var{string}. A negative offset is interpreted relative -to the end of @var{string}, and it is not an error if @var{offset} -exceeds the bounds of @var{string}. - -@example -index(`aba', `a', `1') -@result{}2 -index(`ababa', `ba', `-3') -@result{}3 -index(`abc', `ab', `4') -@result{}-1 -index(`abc', `bc', `-4') -@result{}1 -@end example - -@ignore -@comment Expose a bug in the strstr() algorithm present in glibc -@comment 2.9 through 2.12 and in gnulib up to Sep 2010. - -@example -index(`;:11-:12-:12-:12-:12-:12-:12-:12-:12.:12.:12.:12.:12.:12.:12.:12.:12-:', -`:12-:12-:12-:12-:12-:12-:12-:12-') -@result{}-1 -@end example - -@comment Expose a bug in the gnulib replacement strstr() algorithm -@comment present from Jun 2010 to Feb 2011, including m4 1.4.15. - -@example -index(`..wi.d.', `.d.') -@result{}4 -@end example -@end ignore - -@node Regexp -@section Searching for regular expressions - -@cindex regular expressions -@cindex expressions, regular -@cindex GNU extensions -Searching for regular expressions is done with the builtin -@code{regexp}: - -@deffn {Builtin (gnu)} regexp (@var{string}, @var{regexp}, @var{resyntax}) -@deffnx {Builtin (gnu)} regexp (@var{string}, @var{regexp}, @ - @ovar{replacement}, @ovar{resyntax}) -Searches for @var{regexp} in @var{string}. - -If @var{resyntax} is given, the particular flavor of regular expression -understood with respect to @var{regexp} can be changed from the current -default. @xref{Changeresyntax}, for details of the values that can be -given for this argument. If exactly three arguments given, then the -third argument is treated as @var{resyntax} only if it matches a known -syntax name, otherwise it is treated as @var{replacement}. - -If @var{replacement} is omitted, @code{regexp} expands to the index of -the first match of @var{regexp} in @var{string}. If @var{regexp} does -not match anywhere in @var{string}, it expands to -1. - -If @var{replacement} is supplied, and there was a match, @code{regexp} -changes the expansion to this argument, with @samp{\@var{n}} substituted -by the text matched by the @var{n}th parenthesized sub-expression of -@var{regexp}, up to nine sub-expressions. The escape @samp{\&} is -replaced by the text of the entire regular expression matched. For -all other characters, @samp{\} treats the next character literally. A -warning is issued if there were fewer sub-expressions than the -@samp{\@var{n}} requested, or if there is a trailing @samp{\}. If there -was no match, @code{regexp} expands to the empty string. - -The macro @code{regexp} is recognized only with parameters. -@end deffn - -@example -regexp(`GNUs not Unix', `\<[a-z]\w+') -@result{}5 -regexp(`GNUs not Unix', `\= 0'), `1', - `$0(`$1', eval(`$1 + $2'), `$3')', - eval(`$2 < 0')`$3', `1', ``0', `$1'', - eval(`$2 < 0 && $3 - 0 >= 0 && $1 + $2 + $3 - 0 >= 0'), `1', - `$0(`$1', `0', eval(`$1 + $2 + $3 - 0'))', - eval(`$2 < 0 && $3 - 0 >= 0'), `1', ``0', `0'', - eval(`$2 < 0'), `1', `$0(`$1', `0', `$3')', - `$3', `', ``$2', `$1'', - eval(`$3 - 0 < 0 && $1 - $2 + $3 - 0 >= 0'), `1', - ``$2', eval(`$1 - $2 + $3')', - eval(`$3 - 0 < 0'), `1', ``$2', `0'', - ``$2', `$3'')')dnl -substr(`abcde', `2', `') -@error{}m4trace: -1- _substr(`abcde', `2', `5') -@result{}cde -substr(`abcde', `-3') -@error{}m4trace: -1- _substr(`abcde', `2', `5') -@result{}cde -substr(`abcde', `', `-3') -@error{}m4trace: -1- _substr(`abcde', `0', `2') -@result{}ab -substr(`abcde', `-6') -@error{}m4trace: -1- _substr(`abcde', `0', `5') -@result{}abcde -substr(`abcde', `-6', `5') -@error{}m4trace: -1- _substr(`abcde', `0', `4') -@result{}abcd -substr(`abcde', `-7', `1') -@error{}m4trace: -1- _substr(`abcde', `0', `0') -@result{} -substr(`abcde', `1', `-2') -@error{}m4trace: -1- _substr(`abcde', `1', `2') -@result{}bc -substr(`abcde', `-4', `-1') -@error{}m4trace: -1- _substr(`abcde', `1', `3') -@result{}bcd -substr(`abcde', `4', `-3') -@error{}m4trace: -1- _substr(`abcde', `4', `0') -@result{} -substr(`abcdefghij', `-09', `08') -@error{}m4trace: -1- _substr(`abcdefghij', `1', `8') -@result{}bcdefghi -@end example - -@node Translit -@section Translating characters - -@cindex translating characters -@cindex characters, translating -Character translation is done with @code{translit}: - -@deffn {Builtin (m4)} translit (@var{string}, @var{chars}, @ovar{replacement}) -Expands to @var{string}, with each character that occurs in -@var{chars} translated into the character from @var{replacement} with -the same index. - -If @var{replacement} is shorter than @var{chars}, the excess characters -of @var{chars} are deleted from the expansion; if @var{chars} is -shorter, the excess characters in @var{replacement} are silently -ignored. If @var{replacement} is omitted, all characters in -@var{string} that are present in @var{chars} are deleted from the -expansion. If a character appears more than once in @var{chars}, only -the first instance is used in making the translation. Only a single -translation pass is made, even if characters in @var{replacement} also -appear in @var{chars}. - -As a GNU extension, both @var{chars} and @var{replacement} can -contain character-ranges, e.g., @samp{a-z} (meaning all lowercase -letters) or @samp{0-9} (meaning all digits). To include a dash @samp{-} -in @var{chars} or @var{replacement}, place it first or last in the -entire string, or as the last character of a range. Back-to-back ranges -can share a common endpoint. It is not an error for the last character -in the range to be `larger' than the first. In that case, the range -runs backwards, i.e., @samp{9-0} means the string @samp{9876543210}. -The expansion of a range is dependent on the underlying encoding of -characters, so using ranges is not always portable between machines. - -The macro @code{translit} is recognized only with parameters. -@end deffn - -@example -translit(`GNUs not Unix', `A-Z') -@result{}s not nix -translit(`GNUs not Unix', `a-z', `A-Z') -@result{}GNUS NOT UNIX -translit(`GNUs not Unix', `A-Z', `z-a') -@result{}tmfs not fnix -translit(`+,-12345', `+--1-5', `<;>a-c-a') -@result{}<;>abcba -translit(`abcdef', `aabdef', `bcged') -@result{}bgced -@end example - -In the @sc{ascii} encoding, the first example deletes all uppercase -letters, the second converts lowercase to uppercase, and the third -`mirrors' all uppercase letters, while converting them to lowercase. -The two first cases are by far the most common, even though they are not -portable to @sc{ebcdic} or other encodings. The fourth example shows a -range ending in @samp{-}, as well as back-to-back ranges. The final -example shows that @samp{a} is mapped to @samp{b}, not @samp{c}; the -resulting @samp{b} is not further remapped to @samp{g}; the @samp{d} and -@samp{e} are swapped, and the @samp{f} is discarded. - -Omitting @var{chars} evokes a warning, but still produces output. - -@example -translit(`abc') -@error{}m4:stdin:1: warning: translit: too few arguments: 1 < 2 -@result{}abc -@end example - -@node Patsubst -@section Substituting text by regular expression - -@cindex regular expressions -@cindex expressions, regular -@cindex pattern substitution -@cindex substitution by regular expression -@cindex GNU extensions -Global substitution in a string is done by @code{patsubst}: - -@deffn {Builtin (gnu)} patsubst (@var{string}, @var{regexp}, @ - @ovar{replacement}, @ovar{resyntax}) -Searches @var{string} for matches of @var{regexp}, and substitutes -@var{replacement} for each match. - -If @var{resyntax} is given, the particular flavor of regular expression -understood with respect to @var{regexp} can be changed from the current -default. @xref{Changeresyntax}, for details of the values that can be -given for this argument. Unlike @var{regexp}, if exactly three -arguments given, the third argument is always treated as -@var{replacement}, even if it matches a known syntax name. - -The parts of @var{string} that are not covered by any match of -@var{regexp} are copied to the expansion. Whenever a match is found, the -search proceeds from the end of the match, so a character from -@var{string} will never be substituted twice. If @var{regexp} matches a -string of zero length, the start position for the search is incremented, -to avoid infinite loops. - -When a replacement is to be made, @var{replacement} is inserted into -the expansion, with @samp{\@var{n}} substituted by the text matched by -the @var{n}th parenthesized sub-expression of @var{patsubst}, for up to -nine sub-expressions. The escape @samp{\&} is replaced by the text of -the entire regular expression matched. For all other characters, -@samp{\} treats the next character literally. A warning is issued if -there were fewer sub-expressions than the @samp{\@var{n}} requested, or -if there is a trailing @samp{\}. - -The @var{replacement} argument can be omitted, in which case the text -matched by @var{regexp} is deleted. - -The macro @code{patsubst} is recognized only with parameters. -@end deffn - -When used with two arguments, @code{regexp} returns the position of the -match, but @code{patsubst} deletes the match: - -@example -patsubst(`GNUs not Unix', `^', `OBS: ') -@result{}OBS: GNUs not Unix -patsubst(`GNUs not Unix', `\<', `OBS: ') -@result{}OBS: GNUs OBS: not OBS: Unix -patsubst(`GNUs not Unix', `\w*', `(\&)') -@result{}(GNUs)() (not)() (Unix)() -patsubst(`GNUs not Unix', `\w+', `(\&)') -@result{}(GNUs) (not) (Unix) -patsubst(`GNUs not Unix', `[A-Z][a-z]+') -@result{}GN not@w{ } -patsubst(`GNUs not Unix', `not', `NOT\') -@error{}m4:stdin:6: warning: patsubst: trailing \ ignored in replacement -@result{}GNUs NOT Unix -@end example - -Here is a slightly more realistic example, which capitalizes individual -words or whole sentences, by substituting calls of the macros -@code{upcase} and @code{downcase} into the strings. - -@deffn Composite upcase (@var{text}) -@deffnx Composite downcase (@var{text}) -@deffnx Composite capitalize (@var{text}) -Expand to @var{text}, but with capitalization changed: @code{upcase} -changes all letters to upper case, @code{downcase} changes all letters -to lower case, and @code{capitalize} changes the first character of each -word to upper case and the remaining characters to lower case. -@end deffn - -First, an example of their usage, using implementations distributed in -@file{m4-@value{VERSION}/@/doc/examples/@/capitalize.m4}. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`capitalize.m4') -@result{} -upcase(`GNUs not Unix') -@result{}GNUS NOT UNIX -downcase(`GNUs not Unix') -@result{}gnus not unix -capitalize(`GNUs not Unix') -@result{}Gnus Not Unix -@end example - -Now for the implementation. There is a helper macro @code{_capitalize} -which puts only its first word in mixed case. Then @code{capitalize} -merely parses out the words, and replaces them with an invocation of -@code{_capitalize}. (As presented here, the @code{capitalize} macro has -some subtle flaws. You should try to see if you can find and correct -them; or @pxref{Improved capitalize, , Answers}). - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -undivert(`capitalize.m4')dnl -@result{}divert(`-1') -@result{}# upcase(text) -@result{}# downcase(text) -@result{}# capitalize(text) -@result{}# change case of text, simple version -@result{}define(`upcase', `translit(`$*', `a-z', `A-Z')') -@result{}define(`downcase', `translit(`$*', `A-Z', `a-z')') -@result{}define(`_capitalize', -@result{} `regexp(`$1', `^\(\w\)\(\w*\)', -@result{} `upcase(`\1')`'downcase(`\2')')') -@result{}define(`capitalize', `patsubst(`$1', `\w+', `_$0(`\&')')') -@result{}divert`'dnl -@end example - -If @var{resyntax} is given, @var{regexp} must be given according to -the syntax chosen, though the default regular expression syntax -remains unchanged for other invocations: - -@example -define(`epatsubst', - `builtin(`patsubst', `$1', `$2', `$3', `POSIX_EXTENDED')')dnl -epatsubst(`bar foo baz Foo', `(\w*) (foo|Foo)', `_\1_') -@result{}_bar_ _baz_ -patsubst(`bar foo baz Foo', `\(\w*\) \(foo\|Foo\)', `_\1_') -@result{}_bar_ _baz_ -@end example - -While @code{regexp} replaces the whole input with the replacement as -soon as there is a match, @code{patsubst} replaces each -@emph{occurrence} of a match and preserves non-matching pieces: - -@example -define(`patreg', -`patsubst($@@) -regexp($@@)')dnl -patreg(`bar foo baz Foo', `foo\|Foo', `FOO') -@result{}bar FOO baz FOO -@result{}FOO -patreg(`aba abb 121', `\(.\)\(.\)\1', `\2\1\2') -@result{}bab abb 212 -@result{}bab -@end example - -Omitting @var{regexp} evokes a warning, but still produces output; -contrast this with an empty @var{regexp} argument. - -@example -patsubst(`abc') -@error{}m4:stdin:1: warning: patsubst: too few arguments: 1 < 2 -@result{}abc -patsubst(`abc', `') -@result{}abc -patsubst(`abc', `', `\\-') -@result{}\-a\-b\-c\- -@end example - -@node Format -@section Formatting strings (printf-like) - -@cindex formatted output -@cindex output, formatted -@cindex GNU extensions -Formatted output can be made with @code{format}: - -@deffn {Builtin (gnu)} format (@var{format-string}, @dots{}) -Works much like the C function @code{printf}. The first argument -@var{format-string} can contain @samp{%} specifications which are -satisfied by additional arguments, and the expansion of @code{format} is -the formatted string. - -The macro @code{format} is recognized only with parameters. -@end deffn - -Its use is best described by a few examples: - -@comment This test is a bit fragile, if someone tries to port to a -@comment platform without infinity. -@example -define(`foo', `The brown fox jumped over the lazy dog') -@result{} -format(`The string "%s" uses %d characters', foo, len(foo)) -@result{}The string "The brown fox jumped over the lazy dog" uses 38 characters -format(`%*.*d', `-1', `-1', `1') -@result{}1 -format(`%.0f', `56789.9876') -@result{}56790 -len(format(`%-*X', `5000', `1')) -@result{}5000 -ifelse(format(`%010F', `infinity'), ` INF', `success', - format(`%010F', `infinity'), ` INFINITY', `success', - format(`%010F', `infinity')) -@result{}success -ifelse(format(`%.1A', `1.999'), `0X1.0P+1', `success', - format(`%.1A', `1.999'), `0X2.0P+0', `success', - format(`%.1A', `1.999')) -@result{}success -format(`%g', `0xa.P+1') -@result{}20 -@end example - -Using the @code{forloop} macro defined earlier (@pxref{Forloop}), this -example shows how @code{format} can be used to produce tabular output. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`forloop.m4') -@result{} -forloop(`i', `1', `10', `format(`%6d squared is %10d -', i, eval(i**2))') -@result{} 1 squared is 1 -@result{} 2 squared is 4 -@result{} 3 squared is 9 -@result{} 4 squared is 16 -@result{} 5 squared is 25 -@result{} 6 squared is 36 -@result{} 7 squared is 49 -@result{} 8 squared is 64 -@result{} 9 squared is 81 -@result{} 10 squared is 100 -@result{} -@end example - -The builtin @code{format} is modeled after the ANSI C @samp{printf} -function, and supports these @samp{%} specifiers: @samp{c}, @samp{s}, -@samp{d}, @samp{o}, @samp{x}, @samp{X}, @samp{u}, @samp{a}, @samp{A}, -@samp{e}, @samp{E}, @samp{f}, @samp{F}, @samp{g}, @samp{G}, and -@samp{%}; it supports field widths and precisions, and the flags -@samp{+}, @samp{-}, @samp{ }, @samp{0}, @samp{#}, and @samp{'}. For -integer specifiers, the width modifiers @samp{hh}, @samp{h}, and -@samp{l} are recognized, and for floating point specifiers, the width -modifier @samp{l} is recognized. Items not yet supported include -positional arguments, the @samp{n}, @samp{p}, @samp{S}, and @samp{C} -specifiers, the @samp{z}, @samp{t}, @samp{j}, @samp{L} and @samp{ll} -modifiers, and any platform extensions available in the native -@code{printf}. For more details on the functioning of @code{printf}, -see the C Library Manual, or the POSIX specification (for -example, @samp{%a} is supported even on platforms that haven't yet -implemented C99 hexadecimal floating point output natively). - -@c FIXME - format still needs some improvements. -Warnings are issued for unrecognized specifiers, an improper number of -arguments, or difficulty parsing an argument according to the format -string (such as overflow or extra characters). It is anticipated that a -future release of GNU @code{m4} will support more specifiers. -Likewise, escape sequences are not yet recognized. - -@example -format(`%p', `0') -@error{}m4:stdin:1: warning: format: unrecognized specifier in '%p' -@result{} -format(`%*d', `') -@error{}m4:stdin:2: warning: format: empty string treated as 0 -@error{}m4:stdin:2: warning: format: too few arguments: 2 < 3 -@result{}0 -format(`%.1f', `2a') -@error{}m4:stdin:3: warning: format: non-numeric argument '2a' -@result{}2.0 -@end example - -@ignore -@comment Expose a crash with a bad format string fixed in 1.4.15. -@comment Unfortunately, 8-bit bytes are hard to check for; but the -@comment exit status is enough to sniff the crash in broken versions. - -@example -format(`%'format(`%c', `128')) -@result{} -@error{}ignore -@end example -@end ignore - -@node Arithmetic -@chapter Macros for doing arithmetic - -@cindex arithmetic -@cindex integer arithmetic -Integer arithmetic is included in @code{m4}, with a C-like syntax. As -convenient shorthands, there are builtins for simple increment and -decrement operations. - -@menu -* Incr:: Decrement and increment operators -* Eval:: Evaluating integer expressions -* Mpeval:: Multiple precision arithmetic -@end menu - -@node Incr -@section Decrement and increment operators - -@cindex decrement operator -@cindex increment operator -Increment and decrement of integers are supported using the builtins -@code{incr} and @code{decr}: - -@deffn {Builtin (m4)} incr (@var{number}) -@deffnx {Builtin (m4)} decr (@var{number}) -Expand to the numerical value of @var{number}, incremented -or decremented, respectively, by one. Except for the empty string, the -expansion is empty if @var{number} could not be parsed. - -The macros @code{incr} and @code{decr} are recognized only with -parameters. -@end deffn - -@example -incr(`4') -@result{}5 -decr(`7') -@result{}6 -incr() -@error{}m4:stdin:3: warning: incr: empty string treated as 0 -@result{}1 -decr() -@error{}m4:stdin:4: warning: decr: empty string treated as 0 -@result{}-1 -@end example - -The builtin macros @code{incr} and @code{decr} are recognized only when -given arguments. - -@node Eval -@section Evaluating integer expressions - -@cindex integer expression evaluation -@cindex evaluation, of integer expressions -@cindex expressions, evaluation of integer -Integer expressions are evaluated with @code{eval}: - -@deffn {Builtin (m4)} eval (@var{expression}, @dvar{radix, 10}, @ovar{width}) -Expands to the value of @var{expression}. The expansion is empty -if a problem is encountered while parsing the arguments. If specified, -@var{radix} and @var{width} control the format of the output. - -Calculations are done with signed numbers, using at least 31-bit -precision, but as a GNU extension, @code{m4} will use wider -integers if available. Precision is finite, based on the platform's -notion of @code{intmax_t}, and overflow silently results in wraparound. -A warning is issued if division by zero is attempted, or if -@var{expression} could not be parsed. - -Expressions can contain the following operators, listed in order of -decreasing precedence. - -@table @samp -@item () -Parentheses -@item + - ~ ! -Unary plus and minus, and bitwise and logical negation -@item ** -Exponentiation -@item * / % \ -Multiplication, division, modulo, and ratio -@item + - -Addition and subtraction -@item << >> >>> -Shift left, shift right, unsigned shift right -@item > >= < <= -Relational operators -@item == != -Equality operators -@item & -Bitwise and -@item ^ -Bitwise exclusive-or -@item | -Bitwise or -@item && -Logical and -@item || -Logical or -@item ?: -Conditional ternary -@item , -Sequential evaluation -@end table - -The macro @code{eval} is recognized only with parameters. -@end deffn - -All binary operators, except exponentiation, are left associative. C -operators that perform variable assignment, such as @samp{+=} or -@samp{--}, are not implemented, since @code{eval} only operates on -constants, not variables. Attempting to use them results in an error. -@comment FIXME - since XCU ERN 137 is approved, we could provide an -@comment extension that supported assignment operators. - -Note that some older @code{m4} implementations use @samp{^} as an -alternate operator for the exponentiation, although POSIX -requires the C behavior of bitwise exclusive-or. The precedence of the -negation operators, @samp{~} and @samp{!}, was traditionally lower than -equality. The unary operators could not be used reliably more than once -on the same term without intervening parentheses. The traditional -precedence of the equality operators @samp{==} and @samp{!=} was -identical instead of lower than the relational operators such as -@samp{<}, even through GNU M4 1.4.8. Starting with version -1.4.9, GNU M4 correctly follows POSIX precedence -rules. M4 scripts designed to be portable between releases must be -aware that parentheses may be required to enforce C precedence rules. -Likewise, division by zero, even in the unused branch of a -short-circuiting operator, is not always well-defined in other -implementations. - -Following are some examples where the current version of M4 follows C -precedence rules, but where older versions and some other -implementations of @code{m4} require explicit parentheses to get the -correct result: - -@example -eval(`1 == 2 > 0') -@result{}1 -eval(`(1 == 2) > 0') -@result{}0 -eval(`! 0 * 2') -@result{}2 -eval(`! (0 * 2)') -@result{}1 -eval(`1 | 1 ^ 1') -@result{}1 -eval(`(1 | 1) ^ 1') -@result{}0 -eval(`+ + - ~ ! ~ 0') -@result{}1 -eval(`++0') -@error{}m4:stdin:8: warning: eval: invalid operator: '++0' -@result{} -eval(`1 = 1') -@error{}m4:stdin:9: warning: eval: invalid operator: '1 = 1' -@result{} -eval(`0 |= 1') -@error{}m4:stdin:10: warning: eval: invalid operator: '0 |= 1' -@result{} -eval(`2 || 1 / 0') -@result{}1 -eval(`0 || 1 / 0') -@error{}m4:stdin:12: warning: eval: divide by zero: '0 || 1 / 0' -@result{} -eval(`0 && 1 % 0') -@result{}0 -eval(`2 && 1 % 0') -@error{}m4:stdin:14: warning: eval: modulo by zero: '2 && 1 % 0' -@result{} -@end example - -@cindex GNU extensions -As a GNU extension, @code{eval} supports several operators -that do not appear in C@. A right-associative exponentiation operator -@samp{**} computes the value of the left argument raised to the right, -modulo the numeric precision width. If evaluated, the exponent must be -non-negative, and at least one of the arguments must be non-zero, or a -warning is issued. An unsigned shift operator @samp{>>>} allows -shifting a negative number as though it were an unsigned bit pattern, -which shifts in 0 bits rather than twos-complement sign-extension. A -ratio operator @samp{\} behaves like normal division @samp{/} on -integers, but is provided for symmetry with @code{mpeval}. -Additionally, the C operators @samp{,} and @samp{?:} are supported. - -@example -eval(`2 ** 3 ** 2') -@result{}512 -eval(`(2 ** 3) ** 2') -@result{}64 -eval(`0 ** 1') -@result{}0 -eval(`2 ** 0') -@result{}1 -eval(`0 ** 0') -@result{} -@error{}m4:stdin:5: warning: eval: divide by zero: '0 ** 0' -eval(`4 ** -2') -@error{}m4:stdin:6: warning: eval: negative exponent: '4 ** -2' -@result{} -eval(`2 || 4 ** -2') -@result{}1 -eval(`(-1 >> 1) == -1') -@result{}1 -eval(`(-1 >>> 1) > (1 << 30)') -@result{}1 -eval(`6 \ 3') -@result{}2 -eval(`1 ? 2 : 3') -@result{}2 -eval(`0 ? 2 : 3') -@result{}3 -eval(`1 ? 2 : 1/0') -@result{}2 -eval(`0 ? 1/0 : 3') -@result{}3 -eval(`4, 5') -@result{}5 -@end example - -Within @var{expression}, (but not @var{radix} or @var{width}), numbers -without a special prefix are decimal. A simple @samp{0} prefix -introduces an octal number. @samp{0x} introduces a hexadecimal number. -As GNU extensions, @samp{0b} introduces a binary number. -@samp{0r} introduces a number expressed in any radix between 1 and 36: -the prefix should be immediately followed by the decimal expression of -the radix, a colon, then the digits making the number. For radix 1, -leading zeros are ignored, and all remaining digits must be @samp{1}; -for all other radices, the digits are @samp{0}, @samp{1}, @samp{2}, -@dots{}. Beyond @samp{9}, the digits are @samp{a}, @samp{b} @dots{} up -to @samp{z}. Lower and upper case letters can be used interchangeably -in numbers prefixes and as number digits. - -Parentheses may be used to group subexpressions whenever needed. For the -relational operators, a true relation returns @code{1}, and a false -relation return @code{0}. - -Here are a few examples of use of @code{eval}. - -@example -eval(`-3 * 5') -@result{}-15 -eval(`-99 / 10') -@result{}-9 -eval(`-99 % 10') -@result{}-9 -eval(`99 % -10') -@result{}9 -eval(index(`Hello world', `llo') >= 0) -@result{}1 -eval(`0r1:0111 + 0b100 + 0r3:12') -@result{}12 -define(`square', `eval(`($1) ** 2')') -@result{} -square(`9') -@result{}81 -square(square(`5')` + 1') -@result{}676 -define(`foo', `666') -@result{} -eval(`foo / 6') -@error{}m4:stdin:11: warning: eval: bad expression: 'foo / 6' -@result{} -eval(foo / 6) -@result{}111 -@end example - -As the last two lines show, @code{eval} does not handle macro -names, even if they expand to a valid expression (or part of a valid -expression). Therefore all macros must be expanded before they are -passed to @code{eval}. -@comment update this if we add support for variables. - -Some calculations are not portable to other implementations, since they -have undefined semantics in C, but GNU @code{m4} has -well-defined behavior on overflow. When shifting, an out-of-range shift -amount is implicitly brought into the range of the precision using -modulo arithmetic (for example, on 32-bit integers, this would be an -implicit bit-wise and with 0x1f). This example should work whether your -platform uses 32-bit integers, 64-bit integers, or even some other -atypical size. - -@example -define(`max_int', eval(`-1 >>> 1')) -@result{} -define(`min_int', eval(max_int` + 1')) -@result{} -eval(min_int` < 0') -@result{}1 -eval(max_int` > 0') -@result{}1 -ifelse(eval(min_int` / -1'), min_int, `overflow occurred') -@result{}overflow occurred -eval(`0x80000000 % -1') -@result{}0 -eval(`-4 >> 1') -@result{}-2 -eval(`-4 >> 'eval(len(eval(max_int, `2'))` + 2')) -@result{}-2 -@end example - -If @var{radix} is specified, it specifies the radix to be used in the -expansion. The default radix is 10; this is also the case if -@var{radix} is the empty string. A warning results if the radix is -outside the range of 1 through 36, inclusive. The result of @code{eval} -is always taken to be signed. No radix prefix is output, and for -radices greater than 10, the digits are lower case (although some -other implementations use upper case). The output is unquoted, and -subject to further macro expansion. The @var{width} -argument specifies the minimum output width, excluding any negative -sign. The result is zero-padded to extend the expansion to the -requested width. A warning results if the width is negative. If -@var{radix} or @var{width} is out of bounds, the expansion of -@code{eval} is empty. - -@example -eval(`666', `10') -@result{}666 -eval(`666', `11') -@result{}556 -eval(`666', `6') -@result{}3030 -eval(`666', `6', `10') -@result{}0000003030 -eval(`-666', `6', `10') -@result{}-0000003030 -eval(`10', `', `0') -@result{}10 -`0r1:'eval(`10', `1', `11') -@result{}0r1:01111111111 -eval(`10', `16') -@result{}a -eval(`1', `37') -@error{}m4:stdin:9: warning: eval: radix out of range: 37 -@result{} -eval(`1', , `-1') -@error{}m4:stdin:10: warning: eval: negative width: -1 -@result{} -eval() -@error{}m4:stdin:11: warning: eval: empty string treated as 0 -@result{}0 -eval(` ') -@error{}m4:stdin:12: warning: eval: empty string treated as 0 -@result{}0 -define(`a', `hi')eval(` 10 ', `16') -@result{}hi -@end example - -@node Mpeval -@section Multiple precision arithmetic - -When @code{m4} is compiled with a multiple precision arithmetic library -(@pxref{Experiments}), a builtin @code{mpeval} is defined. - -@deffn {Builtin (mpeval)} mpeval (@var{expression}, @dvar{radix, 10}, @ - @ovar{width}) -Behaves similarly to @code{eval}, except the calculations are done with -infinite precision, and rational numbers are supported. Numbers may be -of any length. - -The macro @code{mpeval} is recognized only with parameters. -@end deffn - -For the most part, using @code{mpeval} is similar to using @code{eval}: - -@comment options: mpeval - -@example -$ @kbd{m4 mpeval -} -mpeval(`(1 << 70) + 2 ** 68 * 3', `16') -@result{}700000000000000000 -`0r24:'mpeval(`0r36:zYx', `24', `5') -@result{}0r24:038m9 -@end example - -The ratio operator, @samp{\}, is provided with the same precedence as -division, and rationally divides two numbers and canonicalizes the -result, whereas the division operator @samp{/} always returns the -integer quotient of the division. To convert a rational value to -integral, divide (@samp{/}) by 1. Some operators, such as @samp{%}, -@samp{<<}, @samp{>>}, @samp{~}, @samp{&}, @samp{|} and @samp{^} operate -only on integers and will truncate any rational remainder. The unsigned -shift operator, @samp{>>>}, behaves identically with regular right -shifts, @samp{>>}, since with infinite precision, it is not possible to -convert a negative number to a positive using shifts. The -exponentiation operator, @samp{**}, assumes that the exponent is -integral, but allows negative exponents. With the short-circuit logical -operators, @samp{||} and @samp{&&}, a non-zero result preserves the -value of the argument that ended evaluation, rather than collapsing to -@samp{1}. The operators @samp{?:} and @samp{,} are always available, -even in POSIX mode, since @code{mpeval} does not have to -conform to the POSIX rules for @code{eval}. - -@comment options: mpeval - -@example -$ @kbd{m4 mpeval -} -mpeval(`2 / 4') -@result{}0 -mpeval(`2 \ 4') -@result{}1\2 -mpeval(`2 || 3') -@result{}2 -mpeval(`1 && 3') -@result{}3 -mpeval(`-1 >> 1') -@result{}-1 -mpeval(`-1 >>> 1') -@result{}-1 -@end example - -@node Shell commands -@chapter Macros for running shell commands - -@cindex UNIX commands, running -@cindex executing shell commands -@cindex running shell commands -@cindex shell commands, running -@cindex commands, running shell -There are a few builtin macros in @code{m4} that allow you to run shell -commands from within @code{m4}. - -Note that the definition of a valid shell command is system dependent. -On UNIX systems, this is the typical @command{/bin/sh}. But on other -systems, such as native Windows, the shell has a different syntax of -commands that it understands. Some examples in this chapter assume -@command{/bin/sh}, and also demonstrate how to quit early with a known -exit value if this is not the case. - -@menu -* Platform macros:: Determining the platform -* Syscmd:: Executing simple commands -* Esyscmd:: Reading the output of commands -* Sysval:: Exit status -* Mkstemp:: Making temporary files -* Mkdtemp:: Making temporary directories -@end menu - -@node Platform macros -@section Determining the platform - -@cindex platform macros -Sometimes it is desirable for an input file to know which platform -@code{m4} is running on. GNU @code{m4} provides several -macros that are predefined to expand to the empty string; checking for -their existence will confirm platform details. - -@deffn {Optional builtin (gnu)} __os2__ -@deffnx {Optional builtin (traditional)} os2 -@deffnx {Optional builtin (gnu)} __unix__ -@deffnx {Optional builtin (traditional)} unix -@deffnx {Optional builtin (gnu)} __windows__ -@deffnx {Optional builtin (traditional)} windows -Each of these macros is conditionally defined as needed to describe the -environment of @code{m4}. If defined, each macro expands to the empty -string. -@end deffn - -On UNIX systems, GNU @code{m4} will define @code{@w{__unix__}} -in the @samp{gnu} module, and @code{unix} in the @samp{traditional} -module. - -On native Windows systems, GNU @code{m4} will define -@code{@w{__windows__}} in the @samp{gnu} module, and @code{windows} in -the @samp{traditional} module. - -On OS/2 systems, GNU @code{m4} will define @code{@w{__os2__}} -in the @samp{gnu} module, and @code{os2} in the @samp{traditional} -module. - -If GNU M4 does not provide a platform macro for your system, -please report that as a bug. - -@example -define(`provided', `0') -@result{} -ifdef(`__unix__', `define(`provided', incr(provided))') -@result{} -ifdef(`__windows__', `define(`provided', incr(provided))') -@result{} -ifdef(`__os2__', `define(`provided', incr(provided))') -@result{} -provided -@result{}1 -@end example - -@node Syscmd -@section Executing simple commands - -Any shell command can be executed, using @code{syscmd}: - -@deffn {Builtin (m4)} syscmd (@var{shell-command}) -Executes @var{shell-command} as a shell command. - -The expansion of @code{syscmd} is void, @emph{not} the output from -@var{shell-command}! Output or error messages from @var{shell-command} -are not read by @code{m4}. @xref{Esyscmd}, if you need to process the -command output. - -Prior to executing the command, @code{m4} flushes its buffers. -The default standard input, output and error of @var{shell-command} are -the same as those of @code{m4}. - -By default, the @var{shell-command} will be used as the argument to the -@option{-c} option of the @command{/bin/sh} shell (or the version of -@command{sh} specified by @samp{command -p getconf PATH}, if your system -supports that). If you prefer a different shell, the -@command{configure} script can be given the option -@option{--with-syscmd-shell=@var{location}} to set the location of an -alternative shell at GNU @code{m4} installation; the -alternative shell must still support @option{-c}. - -When the @option{--safer} option (@pxref{Operation modes, , Invoking -m4}) is in effect, @code{syscmd} results in an error, since otherwise an -input file could execute arbitrary code. - -The macro @code{syscmd} is recognized only with parameters. -@end deffn - -@example -define(`foo', `FOO') -@result{} -syscmd(`echo foo') -@result{}foo -@result{} -@end example - -Note how the expansion of @code{syscmd} keeps the trailing newline of -the command, as well as using the newline that appeared after the macro. - -The following is an example of @var{shell-command} using the same -standard input as @code{m4}: - -@comment The testsuite does not know how to parse pipes from the -@comment texinfo. Fortunately, there are other tests in the testsuite -@comment that test this same feature. -@comment ignore -@example -$ @kbd{echo "m4wrap(\`syscmd(\`cat')')" | m4} -@result{} -@end example - -It tells @code{m4} to read all of its input before executing the wrapped -text, then hands a valid (albeit emptied) pipe as standard input for the -@code{cat} subcommand. Therefore, you should be careful when using -standard input (either by specifying no files, or by passing @samp{-} as -a file name on the command line, @pxref{Command line files, , Invoking -m4}), and also invoking subcommands via @code{syscmd} or @code{esyscmd} -that consume data from standard input. When standard input is a -seekable file, the subprocess will pick up with the next character not -yet processed by @code{m4}; when it is a pipe or other non-seekable -file, there is no guarantee how much data will already be buffered by -@code{m4} and thus unavailable to the child. - -Following is an example of how potentially unsafe actions can be -suppressed. - -@comment options: --safer -@comment status: 1 -@example -$ @kbd{m4 --safer} -syscmd(`echo hi') -@error{}m4:stdin:1: syscmd: disabled by --safer -@result{} -@end example - -@node Esyscmd -@section Reading the output of commands - -@cindex GNU extensions -If you want @code{m4} to read the output of a shell command, use -@code{esyscmd}: - -@deffn {Builtin (gnu)} esyscmd (@var{shell-command}) -Expands to the standard output of the shell command -@var{shell-command}. - -Prior to executing the command, @code{m4} flushes its buffers. -The default standard input and standard error of @var{shell-command} are -the same as those of @code{m4}. The error output of @var{shell-command} -is not a part of the expansion: it will appear along with the error -output of @code{m4}. - -By default, the @var{shell-command} will be used as the argument to the -@option{-c} option of the @command{/bin/sh} shell (or the version of -@command{sh} specified by @samp{command -p getconf PATH}, if your system -supports that). If you prefer a different shell, the -@command{configure} script can be given the option -@option{--with-syscmd-shell=@var{location}} to set the location of an -alternative shell at GNU @code{m4} installation; the -alternative shell must still support @option{-c}. - -When the @option{--safer} option (@pxref{Operation modes, , Invoking -m4}) is in effect, @code{esyscmd} results in an error, since otherwise -an input file could execute arbitrary code. - -The macro @code{esyscmd} is recognized only with parameters. -@end deffn - -@example -define(`foo', `FOO') -@result{} -esyscmd(`echo foo') -@result{}FOO -@result{} -@end example - -Note how the expansion of @code{esyscmd} keeps the trailing newline of -the command, as well as using the newline that appeared after the macro. - -Just as with @code{syscmd}, care must be exercised when sharing standard -input between @code{m4} and the child process of @code{esyscmd}. -Likewise, potentially unsafe actions can be suppressed. - -@comment options: --safer -@comment status: 1 -@example -$ @kbd{m4 --safer} -esyscmd(`echo hi') -@error{}m4:stdin:1: esyscmd: disabled by --safer -@result{} -@end example - -@node Sysval -@section Exit status - -@cindex UNIX commands, exit status from -@cindex exit status from shell commands -@cindex shell commands, exit status from -@cindex commands, exit status from shell -@cindex status of shell commands -To see whether a shell command succeeded, use @code{sysval}: - -@deffn {Builtin (m4)} sysval -Expands to the exit status of the last shell command run with -@code{syscmd} or @code{esyscmd}. Expands to 0 if no command has been -run yet. -@end deffn - -@example -sysval -@result{}0 -syscmd(`false') -@result{} -ifelse(sysval, `0', `zero', `non-zero') -@result{}non-zero -syscmd(`exit 2') -@result{} -sysval -@result{}2 -syscmd(`true') -@result{} -sysval -@result{}0 -esyscmd(`false') -@result{} -ifelse(sysval, `0', `zero', `non-zero') -@result{}non-zero -esyscmd(`echo dnl && exit 127') -@result{} -sysval -@result{}127 -esyscmd(`true') -@result{} -sysval -@result{}0 -@end example - -@code{sysval} results in 127 if there was a problem executing the -command, for example, if the system-imposed argument length is exceeded, -or if there were not enough resources to fork. It is not possible to -distinguish between failed execution and successful execution that had -an exit status of 127, unless there was output from the child process. - -On UNIX platforms, where it is possible to detect when command execution -is terminated by a signal, rather than a normal exit, the result is the -signal number shifted left by eight bits. - -@comment This test has difficulties being portable, even on platforms -@comment where syscmd invokes /bin/sh. Kill is not portable with signal -@comment names. According to autoconf, the only portable signal numbers -@comment are 1 (HUP), 2 (INT), 9 (KILL), 13 (PIPE) and 15 (TERM). But -@comment all shells handle SIGINT, and ksh handles HUP (as in, the shell -@comment exits normally rather than letting the signal terminate it). -@comment Also, TERM is flaky, as it can also kill the running m4 on -@comment systems where /bin/sh does not create its own process group. -@comment And PIPE is unreliable, since people tend to run with it -@comment ignored, with m4 inheriting that choice. That leaves KILL as -@comment the only signal we can reliably test. -@example -dnl This test assumes kill is a shell builtin, and that signals are -dnl recognizable. -ifdef(`__unix__', , - `errprint(` skipping: syscmd does not have unix semantics -')m4exit(`77')')dnl -syscmd(`kill -9 $$') -@result{} -sysval -@result{}2304 -syscmd() -@result{} -sysval -@result{}0 -esyscmd(`kill -9 $$') -@result{} -sysval -@result{}2304 -@end example - -When the @option{--safer} option (@pxref{Operation modes, , Invoking -m4}) is in effect, @code{sysval} will always remain at its default value -of zero. - -@comment options: --safer -@comment status: 1 -@example -$ @kbd{m4 --safer} -sysval -@result{}0 -syscmd(`false') -@error{}m4:stdin:2: syscmd: disabled by --safer -@result{} -sysval -@result{}0 -@end example - -@node Mkstemp -@section Making temporary files - -@cindex temporary file names -@cindex files, names of temporary -Commands specified to @code{syscmd} or @code{esyscmd} might need a -temporary file, for output or for some other purpose. There is a -builtin macro, @code{mkstemp}, for making a temporary file: - -@deffn {Builtin (m4)} mkstemp (@var{template}) -@deffnx {Builtin (m4)} maketemp (@var{template}) -Expands to the quoted name of a new, empty file, made from the string -@var{template}, which should end with the string @samp{XXXXXX}. The six -@samp{X} characters are then replaced with random characters matching -the regular expression @samp{[a-zA-Z0-9._-]}, in order to make the file -name unique. If fewer than six @samp{X} characters are found at the end -of @code{template}, the result will be longer than the template. The -created file will have access permissions as if by @kbd{chmod =rw,go=}, -meaning that the current umask of the @code{m4} process is taken into -account, and at most only the current user can read and write the file. - -The traditional behavior, standardized by POSIX, is that -@code{maketemp} merely replaces the trailing @samp{X} with the process -id, without creating a file or quoting the expansion, and without -ensuring that the resulting -string is a unique file name. In part, this means that using the same -@var{template} twice in the same input file will result in the same -expansion. This behavior is a security hole, as it is very easy for -another process to guess the name that will be generated, and thus -interfere with a subsequent use of @code{syscmd} trying to manipulate -that file name. Hence, POSIX has recommended that all new -implementations of @code{m4} provide the secure @code{mkstemp} builtin, -and that users of @code{m4} check for its existence. - -The expansion is void and an error issued if a temporary file could -not be created. - -When the @option{--safer} option (@pxref{Operation modes, Invoking m4}) -is in effect, @code{mkstemp} and GNU-mode @code{maketemp} -result in an error, since otherwise an input file could perform a mild -denial-of-service attack by filling up a disk with multiple empty files. - -The macros @code{mkstemp} and @code{maketemp} are recognized only with -parameters. -@end deffn - -If you try this next example, you will most likely get different output -for the two file names, since the replacement characters are randomly -chosen: - -@comment ignore -@example -$ @kbd{m4} -define(`tmp', `oops') -@result{} -maketemp(`/tmp/fooXXXXXX') -@error{}m4:stdin:1: warning: maketemp: recommend using mkstemp instead -@result{}/tmp/fooa07346 -ifdef(`mkstemp', `define(`maketemp', defn(`mkstemp'))', - `define(`mkstemp', defn(`maketemp'))dnl -errprint(`warning: potentially insecure maketemp implementation -')') -@result{} -mkstemp(`doc') -@result{}docQv83Uw -@end example - -@comment options: --safer -@comment status: 1 -@example -$ @kbd{m4 --safer} -maketemp(`/tmp/fooXXXXXX') -@error{}m4:stdin:1: warning: maketemp: recommend using mkstemp instead -@error{}m4:stdin:1: maketemp: disabled by --safer -@result{} -mkstemp(`/tmp/fooXXXXXX') -@error{}m4:stdin:2: mkstemp: disabled by --safer -@result{} -@end example - -@cindex GNU extensions -Unless you use the @option{--traditional} command line option (or -@option{-G}, @pxref{Limits control, , Invoking m4}), the GNU -version of @code{maketemp} is secure. This means that using the same -template to multiple calls will generate multiple files. However, we -recommend that you use the new @code{mkstemp} macro, introduced in -GNU M4 1.4.8, which is secure even in traditional mode. Also, -as of M4 1.4.11, the secure implementation quotes the resulting file -name, so that you are guaranteed to know what file was created even if -the random file name happens to match an existing macro. Notice that -this example is careful to use @code{defn} to avoid unintended expansion -of @samp{foo}. - -@example -$ @kbd{m4} -define(`foo', `errprint(`oops')') -@result{} -syscmd(`rm -f foo-??????')sysval -@result{}0 -define(`file1', maketemp(`foo-XXXXXX'))dnl -@error{}m4:stdin:3: warning: maketemp: recommend using mkstemp instead -ifelse(esyscmd(`echo \` foo-?????? \''), `foo-??????', - `no file', `created') -@result{}created -define(`file2', maketemp(`foo-XX'))dnl -@error{}m4:stdin:6: warning: maketemp: recommend using mkstemp instead -define(`file3', mkstemp(`foo-XXXXXX'))dnl -ifelse(len(defn(`file1')), len(defn(`file2')), - `same length', `different') -@result{}same length -ifelse(defn(`file1'), defn(`file2'), `same', `different file') -@result{}different file -ifelse(defn(`file2'), defn(`file3'), `same', `different file') -@result{}different file -ifelse(defn(`file1'), defn(`file3'), `same', `different file') -@result{}different file -syscmd(`rm 'defn(`file1') defn(`file2') defn(`file3')) -@result{} -sysval -@result{}0 -@end example - -@comment options: -G -@example -$ @kbd{m4 -G} -syscmd(`rm -f foo-*')sysval -@result{}0 -define(`file1', maketemp(`foo-XXXXXX'))dnl -@error{}m4:stdin:2: warning: maketemp: recommend using mkstemp instead -define(`file2', maketemp(`foo-XXXXXX'))dnl -@error{}m4:stdin:3: warning: maketemp: recommend using mkstemp instead -ifelse(file1, file2, `same', `different file') -@result{}same -len(maketemp(`foo-XXXXX')) -@error{}m4:stdin:5: warning: maketemp: recommend using mkstemp instead -@result{}9 -define(`abc', `def') -@result{} -maketemp(`foo-abc') -@result{}foo-def -@error{}m4:stdin:7: warning: maketemp: recommend using mkstemp instead -syscmd(`test -f foo-*')sysval -@result{}1 -@end example - -@node Mkdtemp -@section Making temporary directories - -@cindex temporary directory -@cindex directories, temporary -@cindex GNU extensions -Commands specified to @code{syscmd} or @code{esyscmd} might need a -temporary directory, for holding multiple temporary files; such a -directory can be created with @code{mkdtemp}: - -@deffn {Builtin (gnu)} mkdtemp (@var{template}) -Expands to the quoted name of a new, empty directory, made from the string -@var{template}, which should end with the string @samp{XXXXXX}. The six -@samp{X} characters are then replaced with random characters matching -the regular expression @samp{[a-zA-Z0-9._-]}, in order to make the name -unique. If fewer than six @samp{X} characters are found at the end of -@code{template}, the result will be longer than the template. The -created directory will have access permissions as if by @kbd{chmod -=rwx,go=}, meaning that the current umask of the @code{m4} process is -taken into account, and at most only the current user can read, write, -and search the directory. - -The expansion is void and an error issued if a temporary directory could -not be created. - -When the @option{--safer} option (@pxref{Operation modes, Invoking m4}) -is in effect, @code{mkdtemp} results in an error, since otherwise an -input file could perform a mild denial-of-service attack by filling up a -disk with multiple directories. - -The macro @code{mkdtemp} is recognized only with parameters. -This macro was added in M4 2.0. -@end deffn - -If you try this next example, you will most likely get different output -for the directory names, since the replacement characters are randomly -chosen: - -@comment ignore -@example -$ @kbd{m4} -define(`tmp', `oops') -@result{} -mkdtemp(`/tmp/fooXXXXXX') -@result{}/tmp/foo2h89Vo -mkdtemp(`dir) -@result{}dirrg079A -@end example - -@comment options: --safer -@comment status: 1 -@example -$ @kbd{m4 --safer} -mkdtemp(`/tmp/fooXXXXXX') -@error{}m4:stdin:1: mkdtemp: disabled by --safer -@result{} -@end example - -Multiple calls with the same template will generate multiple -directories. - -@example -$ @kbd{m4} -syscmd(`echo foo??????')dnl -@result{}foo?????? -define(`dir1', mkdtemp(`fooXXXXXX'))dnl -ifelse(esyscmd(`echo foo??????'), `foo??????', `no dir', `created') -@result{}created -define(`dir2', mkdtemp(`fooXXXXXX'))dnl -ifelse(dir1, dir2, `same', `different directories') -@result{}different directories -syscmd(`rmdir 'dir1 dir2) -@result{} -sysval -@result{}0 -@end example - -@node Miscellaneous -@chapter Miscellaneous builtin macros - -This chapter describes various builtins, that do not really belong in -any of the previous chapters. - -@menu -* Errprint:: Printing error messages -* Location:: Printing current location -* M4exit:: Exiting from @code{m4} -* Syncoutput:: Turning on and off sync lines -@end menu - -@node Errprint -@section Printing error messages - -@cindex printing error messages -@cindex error messages, printing -@cindex messages, printing error -@cindex standard error, output to -You can print error messages using @code{errprint}: - -@deffn {Builtin (m4)} errprint (@var{message}, @dots{}) -Prints @var{message} and the rest of the arguments to standard error, -separated by spaces. Standard error is used, regardless of the -@option{--debugfile} option (@pxref{Debugging options, , Invoking m4}). - -The expansion of @code{errprint} is void. -The macro @code{errprint} is recognized only with parameters. -@end deffn - -@example -errprint(`Invalid arguments to forloop -') -@error{}Invalid arguments to forloop -@result{} -errprint(`1')errprint(`2',`3 -') -@error{}12 3 -@result{} -@end example - -A trailing newline is @emph{not} printed automatically, so it should be -supplied as part of the argument, as in the example. Unfortunately, the -exact output of @code{errprint} is not very portable to other @code{m4} -implementations: POSIX requires that all arguments be printed, -but some implementations of @code{m4} only print the first. -Furthermore, some BSD implementations always append a newline -for each @code{errprint} call, regardless of whether the last argument -already had one, and POSIX is silent on whether this is -acceptable. - -@node Location -@section Printing current location - -@cindex location, input -@cindex input location -To make it possible to specify the location of an error, three -utility builtins exist: - -@deffn {Builtin (gnu)} __file__ -@deffnx {Builtin (gnu)} __line__ -@deffnx {Builtin (gnu)} __program__ -Expand to the quoted name of the current input file, the -current input line number in that file, and the quoted name of the -current invocation of @code{m4}. -@end deffn - -@example -errprint(__program__:__file__:__line__: `input error -') -@error{}m4:stdin:1: input error -@result{} -@end example - -Line numbers start at 1 for each file. If the file was found due to the -@option{-I} option or @env{M4PATH} environment variable, that is -reflected in the file name. Synclines, via @code{syncoutput} -(@pxref{Syncoutput}) or the command line option @option{--synclines} -(or @option{-s}, @pxref{Preprocessor features, , Invoking m4}), and the -@samp{f} and @samp{l} flags of @code{debugmode} (@pxref{Debugmode}), -also use this notion of current file and line. Redefining the three -location macros has no effect on syncline, debug, warning, or error -message output. - -This example reuses the file @file{incl.m4} mentioned earlier -(@pxref{Include}): - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -define(`foo', ``$0' called at __file__:__line__') -@result{} -foo -@result{}foo called at stdin:2 -include(`incl.m4') -@result{}Include file start -@result{}foo called at doc/examples/incl.m4:2 -@result{}Include file end -@result{} -@end example - -The location of macros invoked during the rescanning of macro expansion -text corresponds to the location in the file where the expansion was -triggered, regardless of how many newline characters the expansion text -contains. As of GNU M4 1.4.8, the location of text wrapped -with @code{m4wrap} (@pxref{M4wrap}) is the point at which the -@code{m4wrap} was invoked. Previous versions, however, behaved as -though wrapped text came from line 0 of the file ``''. - -@example -define(`echo', `$@@') -@result{} -define(`foo', `echo(__line__ -__line__)') -@result{} -echo(__line__ -__line__) -@result{}4 -@result{}5 -m4wrap(`foo -') -@result{} -foo(errprint(__line__ -__line__ -)) -@error{}8 -@error{}9 -@result{}8 -@result{}8 -__line__ -@result{}11 -m4wrap(`__line__ -') -@result{} -^D -@result{}6 -@result{}6 -@result{}12 -@end example - -The @code{@w{__program__}} macro behaves like @samp{$0} in shell -terminology. If you invoke @code{m4} through an absolute path or a link -with a different spelling, rather than by relying on a @env{PATH} search -for plain @samp{m4}, it will affect how @code{@w{__program__}} expands. -The intent is that you can use it to produce error messages with the -same formatting that @code{m4} produces internally. It can also be used -within @code{syscmd} (@pxref{Syscmd}) to pick the same version of -@code{m4} that is currently running, rather than whatever version of -@code{m4} happens to be first in @env{PATH}. It was first introduced in -GNU M4 1.4.6. - -@node M4exit -@section Exiting from @code{m4} - -@cindex exiting from @code{m4} -@cindex status, setting @code{m4} exit -If you need to exit from @code{m4} before the entire input has been -read, you can use @code{m4exit}: - -@deffn {Builtin (m4)} m4exit (@ovar{code}) -Causes @code{m4} to exit, with exit status @var{code}. If @var{code} is -left out, the exit status is zero. If @var{code} cannot be parsed, or -is outside the range of 0 to 255, the exit status is one. No further -input is read, and all wrapped and diverted text is discarded. -@end deffn - -@example -m4wrap(`This text is lost due to `m4exit'.') -@result{} -divert(`1') So is this. -divert -@result{} -m4exit And this is never read. -@end example - -A common use of this is to abort processing: - -@deffn Composite fatal_error (@var{message}) -Abort processing with an error message and non-zero status. Prefix -@var{message} with details about where the error occurred, and print the -resulting string to standard error. -@end deffn - -@comment status: 1 -@example -define(`fatal_error', - `errprint(__program__:__file__:__line__`: fatal error: $* -')m4exit(`1')') -@result{} -fatal_error(`this is a BAD one, buster') -@error{}m4:stdin:4: fatal error: this is a BAD one, buster -@end example - -After this macro call, @code{m4} will exit with exit status 1. This macro -is only intended for error exits, since the normal exit procedures are -not followed, i.e., diverted text is not undiverted, and saved text -(@pxref{M4wrap}) is not reread. (This macro could be made more robust -to earlier versions of @code{m4}. You should try to see if you can find -weaknesses and correct them; or @pxref{Improved fatal_error, , Answers}). - -Note that it is still possible for the exit status to be different than -what was requested by @code{m4exit}. If @code{m4} detects some other -error, such as a write error on standard output, the exit status will be -non-zero even if @code{m4exit} requested zero. - -If standard input is seekable, then the file will be positioned at the -next unread character. If it is a pipe or other non-seekable file, -then there are no guarantees how much data @code{m4} might have read -into buffers, and thus discarded. - -@node Syncoutput -@section Turning on and off sync lines - -@cindex toggling synchronization lines -@cindex synchronization lines -@cindex location, input -@cindex input location -It is possible to adjust whether synclines are printed to output: - -@deffn {Builtin (gnu)} syncoutput (@var{truth}) -If @var{truth} matches the extended regular expression -@samp{^[1yY]|^([oO][nN])}, it causes @code{m4} to emit sync lines of the -form: @samp{#line [""]}. - -If @var{truth} is empty, or matches the extended regular expression -@samp{^[0nN]|^([oO][fF])}, it causes @code{m4} to turn sync lines off. - -All other arguments are ignored and issue a warning. - -The macro @code{syncoutput} is recognized only with parameters. -This macro was added in M4 2.0. -@end deffn - -@example -define(`twoline', `1 -2') -@result{} -changecom(`/*', `*/') -@result{} -define(`comment', `/*1 -2*/') -@result{} -twoline -@result{}1 -@result{}2 -dnl no line -syncoutput(`on') -@result{}#line 8 "stdin" -@result{} -twoline -@result{}1 -@result{}#line 9 -@result{}2 -dnl no line -hello -@result{}#line 11 -@result{}hello -comment -@result{}/*1 -@result{}2*/ -one comment `two -three' -@result{}#line 13 -@result{}one /*1 -@result{}2*/ two -@result{}three -goodbye -@result{}#line 15 -@result{}goodbye -syncoutput(`off') -@result{} -twoline -@result{}1 -@result{}2 -syncoutput(`blah') -@error{}m4:stdin:18: warning: syncoutput: unknown directive 'blah' -@result{} -@end example - -Notice that a syncline is output any time a single source line expands -to multiple output lines, or any time multiple source lines expand to a -single output line. When there is a one-for-one correspondence, no -additional synclines are needed. - -Synchronization lines can be used to track where input comes from; an -optional file designation is printed when the syncline algorithm -detects that consecutive output lines come from different files. You -can also use the @option{--synclines} command-line option (or -@option{-s}, @pxref{Preprocessor features, , Invoking m4}) to start -with synchronization on. This example reuses the file @file{incl.m4} -mentioned earlier (@pxref{Include}): - -@comment examples -@comment options: -s -@example -$ @kbd{m4 --synclines -I doc/examples} -include(`incl.m4') -@result{}#line 1 "doc/examples/incl.m4" -@result{}Include file start -@result{}foo -@result{}Include file end -@result{}#line 1 "stdin" -@result{} -@end example - -@node Frozen files -@chapter Fast loading of frozen state - -Some bigger @code{m4} applications may be built over a common base -containing hundreds of definitions and other costly initializations. -Usually, the common base is kept in one or more declarative files, -which files are listed on each @code{m4} invocation prior to the -user's input file, or else each input file uses @code{include}. - -Reading the common base of a big application, over and over again, may -be time consuming. GNU @code{m4} offers some machinery to -speed up the start of an application using lengthy common bases. - -@menu -* Using frozen files:: Using frozen files -* Frozen file format 1:: Frozen file format 1 -* Frozen file format 2:: Frozen file format 2 -@end menu - -@node Using frozen files -@section Using frozen files - -@cindex fast loading of frozen files -@cindex frozen files for fast loading -@cindex initialization, frozen state -@cindex dumping into frozen file -@cindex reloading a frozen file -@cindex GNU extensions -Suppose a user has a library of @code{m4} initializations in -@file{base.m4}, which is then used with multiple input files: - -@comment ignore -@example -$ @kbd{m4 base.m4 input1.m4} -$ @kbd{m4 base.m4 input2.m4} -$ @kbd{m4 base.m4 input3.m4} -@end example - -Rather than spending time parsing the fixed contents of @file{base.m4} -every time, the user might rather execute: - -@comment ignore -@example -$ @kbd{m4 -F base.m4f base.m4} -@end example - -@noindent -once, and further execute, as often as needed: - -@comment ignore -@example -$ @kbd{m4 -R base.m4f input1.m4} -$ @kbd{m4 -R base.m4f input2.m4} -$ @kbd{m4 -R base.m4f input3.m4} -@end example - -@noindent -with the varying input. The first call, containing the @option{-F} -option, only reads and executes file @file{base.m4}, defining -various application macros and computing other initializations. -Once the input file @file{base.m4} has been completely processed, GNU -@code{m4} produces in @file{base.m4f} a @dfn{frozen} file, that is, a -file which contains a kind of snapshot of the @code{m4} internal state. - -Later calls, containing the @option{-R} option, are able to reload -the internal state of @code{m4}, from @file{base.m4f}, -@emph{prior} to reading any other input files. This means -instead of starting with a virgin copy of @code{m4}, input will be -read after having effectively recovered the effect of a prior run. -In our example, the effect is the same as if file @file{base.m4} has -been read anew. However, this effect is achieved a lot faster. - -Only one frozen file may be created or read in any one @code{m4} -invocation. It is not possible to recover two frozen files at once. -However, frozen files may be updated incrementally, through using -@option{-R} and @option{-F} options simultaneously. For example, if -some care is taken, the command: - -@comment ignore -@example -$ @kbd{m4 file1.m4 file2.m4 file3.m4 file4.m4} -@end example - -@noindent -could be broken down in the following sequence, accumulating the same -output: - -@comment ignore -@example -$ @kbd{m4 -F file1.m4f file1.m4} -$ @kbd{m4 -R file1.m4f -F file2.m4f file2.m4} -$ @kbd{m4 -R file2.m4f -F file3.m4f file3.m4} -$ @kbd{m4 -R file3.m4f file4.m4} -@end example - -Some care is necessary because the frozen file does not save all state -information. Stacks of macro definitions via @code{pushdef} are -accurately stored, along with all renamed or undefined builtins, as are -the current syntax rules such as from @code{changequote}. However, the -value of @code{sysval} and text saved in @code{m4wrap} are not currently -preserved. Also, changing command line options between runs may cause -unexpected behavior. A future release of GNU M4 may improve -on the quality of frozen files. - -When an @code{m4} run is to be frozen, the automatic undiversion -which takes place at end of execution is inhibited. Instead, all -positively numbered diversions are saved into the frozen file. -The active diversion number is also transmitted. - -A frozen file to be reloaded need not reside in the current directory. -It is looked up the same way as an @code{include} file (@pxref{Search -Path}). - -If the frozen file was generated with a newer version of @code{m4}, and -contains directives that an older @code{m4} cannot parse, attempting to -load the frozen file with option @option{-R} will cause @code{m4} to -exit with status 63 to indicate version mismatch. - -@node Frozen file format 1 -@section Frozen file format 1 - -@cindex frozen file format 1 -@cindex file format, frozen file version 1 -Frozen files are sharable across architectures. It is safe to write -a frozen file on one machine and read it on another, given that the -second machine uses the same or newer version of GNU @code{m4}. -It is conventional, but not required, to give a frozen file the suffix -of @code{.m4f}. - -Older versions of GNU @code{m4} create frozen files with -syntax version 1. These files can be read by the current version, but -are no longer produced. Version 1 files are mostly text files, although -any macros or diversions that contained nonprintable characters or long -lines cause the resulting frozen file to do likewise, since there are no -escape sequences. The file can be edited to change the state that -@code{m4} will start with. It is composed of several directives, each -starting with a single letter and ending with a newline (@key{NL}). -Wherever a directive is expected, the character @samp{#} can be used -instead to introduce a comment line; empty lines are also ignored if -they are not part of an embedded string. - -In the following descriptions, each @var{len} refers to the length of a -corresponding subsequent @var{str}. Numbers are always expressed in -decimal, and an omitted number defaults to 0. The valid directives in -version 1 are: - -@table @code -@item V @var{number} @key{NL} -Confirms the format of the file. Version 1 is recognized when -@var{number} is 1. This directive must be the first non-comment in the -file, and may not appear more than once. - -@item C @var{len1} , @var{len2} @key{NL} @var{str1} @var{str2} @key{NL} -Uses @var{str1} and @var{str2} as the begin-comment and -end-comment strings. If omitted, then @samp{#} and @key{NL} are the -comment delimiters. - -@item D @var{number}, @var{len} @key{NL} @var{str} @key{NL} -Selects diversion @var{number}, making it current, then copy @var{str} -in the current diversion. @var{number} may be a negative number for a -diversion that discards text. To merely specify an active selection, -use this command with an empty @var{str}. With 0 as the diversion -@var{number}, @var{str} will be issued on standard output at reload -time. GNU @code{m4} will not produce the @samp{D} directive -with non-zero length for diversion 0, but this can be done with manual -edits. This directive may appear more than once for the same diversion, -in which case the diversion is the concatenation of the various uses. -If omitted, then diversion 0 is current. - -@item F @var{len1} , @var{len2} @key{NL} @var{str1} @var{str2} @key{NL} -Defines, through @code{pushdef}, a definition for @var{str1} expanding -to the function whose builtin name is @var{str2}. If the builtin does -not exist (for example, if the frozen file was produced by a copy of -@code{m4} compiled with the now-abandoned @code{changeword} support), -the reload is silent, but any subsequent use of the definition of -@var{str1} will result in a warning. This directive may appear more -than once for the same name, and its order, along with @samp{T}, is -important. If omitted, you will have no access to any builtins. - -@item Q @var{len1} , @var{len2} @key{NL} @var{str1} @var{str2} @key{NL} -Uses @var{str1} and @var{str2} as the begin-quote and end-quote -strings. If omitted, then @samp{`} and @samp{'} are the quote -delimiters. - -@item T @var{len1} , @var{len2} @key{NL} @var{str1} @var{str2} @key{NL} -Defines, though @code{pushdef}, a definition for @var{str1} -expanding to the text given by @var{str2}. This directive may appear -more than once for the same name, and its order, along with @samp{F}, is -important. -@end table - -When loading format 1, the syntax categories @samp{@{} and @samp{@}} are -disabled (reverting braces to be treated like plain characters). This -is because frozen files created with M4 1.4.x did not understand -@samp{$@{@dots{}@}} extended argument notation, and a frozen macro that -contained this character sequence should not behave differently just -because a newer version of M4 reloaded the file. - -@node Frozen file format 2 -@section Frozen file format 2 - -@cindex frozen file format 2 -@cindex file format, frozen file version 2 -The syntax of version 1 has some drawbacks; if any macro or diversion -contained non-printable characters or long lines, the resulting frozen -file would not qualify as a text file, making it harder to edit with -some vendor tools. The concatenation of multiple strings on a single -line, such as for the @samp{T} directive, makes distinguishing the two -strings a bit more difficult. Finally, the format lacks support for -several items of @code{m4} state, such that a reloaded file did not -always behave the same as the original file. - -These shortcomings have been addressed in version 2 of the frozen file -syntax. New directives have been added, and existing directives have -additional, and sometimes optional, parameters. All @var{str} instances -in the grammar are now followed by @key{NL}, which makes the split -between consecutive strings easier to recognize. Strings may now -contain escape sequences modeled after C, such as @samp{\n} for newline -or @samp{\0} for @sc{nul}, so that the frozen file can be pure -@sc{ascii} (although when hand-editing a frozen file, it is still -acceptable to use the original byte rather than an escape sequence for -all bytes except @samp{\}). Also in the context of a @var{str}, the -escape sequence @samp{\@key{NL}} is discarded, allowing a user to split -lines that are too long for some platform tools. - -@table @code -@item V @var{number} @key{NL} -Confirms the format of the file. @code{m4} @value{VERSION} only creates -frozen files where @var{number} is 2. This directive must be the first -non-comment in the file, and may not appear more than once. - -@item C @var{len1} , @var{len2} @key{NL} @var{str1} @key{NL} @var{str2} @key{NL} -Uses @var{str1} and @var{str2} as the begin-comment and -end-comment strings. If omitted, then @samp{#} and @key{NL} are the -comment delimiters. - -@item d @var{len} @key{NL} @var{str} @key{NL} -Sets the debug flags, using @var{str} as the argument to -@code{debugmode}. If omitted, then the debug flags start in their -default disabled state. - -@item D @var{number} , @var{len} @key{NL} @var{str} @key{NL} -Selects diversion @var{number}, making it current, then copy @var{str} -in the current diversion. @var{number} may be a negative number for a -diversion that discards text. To merely specify an active selection, -use this command with an empty @var{string}. With 0 as the diversion -@var{number}, @var{str} will be issued on standard output at reload -time. GNU @code{m4} will not produce the @samp{D} directive -with non-zero length for diversion 0, but this can be done with manual -edits. This directive may appear more than once for the same diversion, -in which case the diversion is the concatenation of the various uses. -If omitted, then diversion 0 is current. - -@comment FIXME - the first usage, with only one string, is not supported -@comment in the current code -@c @item F @var{len1} @key{NL} @var{str1} @key{NL} -@item F @var{len1} , @var{len2} @key{NL} @var{str1} @key{NL} @var{str2} @key{NL} -@itemx F @var{len1} , @var{len2} , @var{len3} @key{NL} @var{str1} @key{NL} @var{str2} @key{NL} @var{str3} @key{NL} -Defines, through @code{pushdef}, a definition for @var{str1} expanding -to the function whose builtin name is given by @var{str2} (defaulting to -@var{str1} if not present). With two arguments, the builtin name is -searched for among the intrinsic builtin functions only; with three -arguments, the builtin name is searched for amongst the builtin -functions defined by the module named by @var{str3}. - -@item M @var{len} @key{NL} @var{str} @key{NL} -Names a module which will be searched for according to the module search -path and loaded. Modules loaded from a frozen file don't add their -builtin entries to the symbol table. Modules must be loaded prior to -specifying module-specific builtins via the three-argument @code{F} or -@code{T}. - -@item Q @var{len1} , @var{len2} @key{NL} @var{str1} @key{NL} @var{str2} @key{NL} -Uses @var{str1} and @var{str2} as the begin-quote and end-quote strings. -If omitted, then @samp{`} and @samp{'} are the quote delimiters. - -@item R @var{len} @key{NL} @var{str} @key{NL} -Sets the default regexp syntax, where @var{str} encodes one of the -regular expression syntaxes supported by GNU M4. -@xref{Changeresyntax}, for more details. - -@item S @var{syntax-code} @var{len} @key{NL} @var{str} @key{NL} -Defines, through @code{changesyntax}, a syntax category for each of the -characters in @var{str}. The @var{syntax-code} must be one of the -characters described in @ref{Changesyntax}. - -@item t @var{len} @key{NL} @var{str} @key{NL} -Enables tracing for any macro named @var{str}, similar to using the -@code{traceon} builtin. This option may occur more than once for -multiple macros; if omitted, no macro starts out as traced. - -@item T @var{len1} , @var{len2} @key{NL} @var{str1} @key{NL} @var{str2} @key{NL} -@itemx T @var{len1} , @var{len2} , @var{len3} @key{NL} @var{str1} @key{NL} @var{str2} @key{NL} @var{str3} @key{NL} -Defines, though @code{pushdef}, a definition for @var{str1} expanding to -the text given by @var{str2}. This directive may appear more than once -for the same name, and its order, along with @samp{F}, is important. If -present, the optional third argument associates the macro with a module -named by @var{str3}. -@end table - -@node Compatibility -@chapter Compatibility with other versions of @code{m4} - -@cindex compatibility -This chapter describes the many of the differences between this -implementation of @code{m4}, and of other implementations found under -UNIX, such as System V Release 4, Solaris, and BSD flavors. -In particular, it lists the known differences and extensions to -POSIX. However, the list is not necessarily comprehensive. - -At the time of this writing, POSIX 2001 (also known as IEEE -Std 1003.1-2001) is the latest standard, although a new version of -POSIX is under development and includes several proposals for -modifying what @code{m4} is required to do. The requirements for -@code{m4} are shared between SUSv3 and POSIX, and -can be viewed at -@uref{http://www.opengroup.org/onlinepubs/@/000095399/@/utilities/@/m4.html}. - -@menu -* Extensions:: Extensions in GNU M4 -* Incompatibilities:: Other incompatibilities -* Experiments:: Experimental features in GNU M4 -@end menu - -@node Extensions -@section Extensions in GNU M4 - -@cindex GNU extensions -@cindex POSIX -@cindex @env{POSIXLY_CORRECT} -This version of @code{m4} contains a few facilities that do not exist -in System V @code{m4}. These extra facilities are all suppressed by -using the @option{-G} command line option, unless overridden by other -command line options. -Most of these extensions are compatible with -@uref{http://www.unix.org/single_unix_specification/, -POSIX}; the few exceptions are suppressed if the -@env{POSIXLY_CORRECT} environment variable is set. - -@itemize @bullet -@item -In the @code{$@var{n}} notation for macro arguments, @var{n} can contain -several digits, while the System V @code{m4} only accepts one digit. -This allows macros in GNU @code{m4} to take any number of -arguments, and not only nine (@pxref{Arguments}). -POSIX does not allow this extension, so it is disabled if -@env{POSIXLY_CORRECT} is set. -@c FIXME - update this bullet when ${11} is implemented. - -@item -The @code{divert} (@pxref{Divert}) macro can manage more than 9 -diversions. GNU @code{m4} treats all positive numbers as valid -diversions, rather than discarding diversions greater than 9. - -@item -Files included with @code{include} and @code{sinclude} are sought in a -user specified search path, if they are not found in the working -directory. The search path is specified by the @option{-I} option and the -@samp{M4PATH} environment variable (@pxref{Search Path}). - -@item -Arguments to @code{undivert} can be non-numeric, in which case the named -file will be included uninterpreted in the output (@pxref{Undivert}). - -@item -Formatted output is supported through the @code{format} builtin, which -is modeled after the C library function @code{printf} (@pxref{Format}). - -@item -Searches and text substitution through regular expressions are supported -by the @code{regexp} (@pxref{Regexp}) and @code{patsubst} -(@pxref{Patsubst}) builtins. - -The syntax of regular expressions in M4 has never been clearly -formalized. While OpenBSD M4 uses extended regular -expressions for @code{regexp} and @code{patsubst}, GNU M4 -defaults to basic regular expressions, but provides -@code{changeresyntax} (@pxref{Changeresyntax}) to change the flavor of -regular expression syntax in use. - -@item -The output of shell commands can be read into @code{m4} with -@code{esyscmd} (@pxref{Esyscmd}). - -@item -There is indirect access to any builtin macro with @code{builtin} -(@pxref{Builtin}). - -@item -Macros can be called indirectly through @code{indir} (@pxref{Indir}). - -@item -The name of the program, the current input file, and the current input -line number are accessible through the builtins @code{@w{__program__}}, -@code{@w{__file__}}, and @code{@w{__line__}} (@pxref{Location}). - -@item -The generation of sync lines can be controlled through @code{syncoutput} -(@pxref{Syncoutput}). - -@item -The format of the output from @code{dumpdef} and macro tracing can be -controlled with @code{debugmode} (@pxref{Debugmode}). - -@item -The destination of trace and debug output can be controlled with -@code{debugfile} (@pxref{Debugfile}). - -@item -The @code{maketemp} (@pxref{Mkstemp}) macro behaves like @code{mkstemp}, -creating a new file with a unique name on every invocation, rather than -following the insecure behavior of replacing the trailing @samp{X} -characters with the @code{m4} process id. POSIX does not -allow this extension, so @code{maketemp} is insecure if -@env{POSIXLY_CORRECT} is set, but you should be using @code{mkstemp} in -the first place. - -@item -POSIX only requires support for the command line options -@option{-s}, @option{-D}, and @option{-U}, so all other options accepted -by GNU M4 are extensions. @xref{Invoking m4}, for a -description of these options. - -@item -The debugging and tracing facilities in GNU @code{m4} are much -more extensive than in most other versions of @code{m4}. - -@item -Some traditional implementations only allow reading standard input -once, but GNU @code{m4} correctly handles multiple instances -of @samp{-} on the command line. - -@item -POSIX requires @code{m4wrap} (@pxref{M4wrap}) to act in FIFO -(first-in, first-out) order, and most other implementations obey this. -However, versions of GNU @code{m4} earlier than 1.6 used -LIFO order. Furthermore, POSIX states that only the first -argument to @code{m4wrap} is saved for later evaluation, but -GNU @code{m4} saves and processes all arguments, with output -separated by spaces. - -@item -POSIX states that builtins that require arguments, but are -called without arguments, have undefined behavior. Traditional -implementations simply behave as though empty strings had been passed. -For example, @code{a`'define`'b} would expand to @code{ab}. But -GNU @code{m4} ignores certain builtins if they have missing -arguments, giving @code{adefineb} for the above example. -@end itemize - -@node Incompatibilities -@section Other incompatibilities - -There are a few other incompatibilities between this implementation of -@code{m4}, and what POSIX requires, or what the System V -version implemented. - -@itemize @bullet -@item -Traditional implementations handle @code{define(`f',`1')} (@pxref{Define}) -by undefining the entire stack of previous definitions, and if doing -@code{undefine(`f')} first. GNU @code{m4} replaces just the top -definition on the stack, as if doing @code{popdef(`f')} followed by -@code{pushdef(`f',`1')}. POSIX allows either behavior. - -@item -At one point, POSIX required @code{changequote(@var{arg})} -(@pxref{Changequote}) to use newline as the close quote, but this was a -bug, and the next version of POSIX is anticipated to state -that using empty strings or just one argument is unspecified. -Meanwhile, the GNU @code{m4} behavior of treating an empty -end-quote delimiter as @samp{'} is not portable, as Solaris treats it as -repeating the start-quote delimiter, and BSD treats it as leaving the -previous end-quote delimiter unchanged. For predictable results, never -call changequote with just one argument, or with empty strings for -arguments. - -@item -At one point, POSIX required @code{changecom(@var{arg},)} -(@pxref{Changecom}) to make it impossible to end a comment, but this is -a bug, and the next version of POSIX is anticipated to state -that using empty strings is unspecified. Meanwhile, the GNU -@code{m4} behavior of treating an empty end-comment delimiter as newline -is not portable, as BSD treats it as leaving the previous end-comment -delimiter unchanged. It is also impossible in BSD implementations to -disable comments, even though that is required by POSIX. For -predictable results, never call changecom with empty strings for -arguments. - -@item -Traditional implementations allow argument collection, but not string -and comment processing, to span file boundaries. Thus, if @file{a.m4} -contains @samp{len(}, and @file{b.m4} contains @samp{abc)}, -@kbd{m4 a.m4 b.m4} outputs @samp{3} with traditional @code{m4}, but -gives an error message that the end of file was encountered inside a -macro with GNU @code{m4}. On the other hand, traditional -implementations do end of file processing for files included with -@code{include} or @code{sinclude} (@pxref{Include}), while GNU -@code{m4} seamlessly integrates the content of those files. Thus -@code{include(`a.m4')include(`b.m4')} will output @samp{3} instead of -giving an error. - -@item -POSIX requires @code{eval} (@pxref{Eval}) to treat all -operators with the same precedence as C@. However, earlier versions of -GNU @code{m4} followed the traditional behavior of other -@code{m4} implementations, where bitwise and logical negation (@samp{~} -and @samp{!}) have lower precedence than equality operators; and where -equality operators (@samp{==} and @samp{!=}) had the same precedence as -relational operators (such as @samp{<}). Use explicit parentheses to -ensure proper precedence. As extensions to POSIX, -GNU @code{m4} gives well-defined semantics to operations that -C leaves undefined, such as when overflow occurs, when shifting negative -numbers, or when performing division by zero. POSIX also -requires @samp{=} to cause an error, but many traditional -implementations allowed it as an alias for @samp{==}. - -@item -POSIX 2001 requires @code{translit} (@pxref{Translit}) to -treat each character of the second and third arguments literally. -However, it is anticipated that the next version of POSIX will -allow the GNU @code{m4} behavior of treating @samp{-} as a -range operator. - -@item -POSIX requires @code{m4} to honor the locale environment -variables of @env{LANG}, @env{LC_ALL}, @env{LC_CTYPE}, -@env{LC_MESSAGES}, and @env{NLSPATH}, but this has not yet been -implemented in GNU @code{m4}. - -@item -GNU @code{m4} implements sync lines differently from System V -@code{m4}, when text is being diverted. GNU @code{m4} outputs -the sync lines when the text is being diverted, and System V @code{m4} -when the diverted text is being brought back. - -The problem is which lines and file names should be attached to text -that is being, or has been, diverted. System V @code{m4} regards all -the diverted text as being generated by the source line containing the -@code{undivert} call, whereas GNU @code{m4} regards the -diverted text as being generated at the time it is diverted. - -The sync line option is used mostly when using @code{m4} as -a front end to a compiler. If a diverted line causes a compiler error, -the error messages should most probably refer to the place where the -diversion was made, and not where it was inserted again. - -@comment options: -s -@example -divert(2)2 -divert(1)1 -divert`'0 -@result{}#line 3 "stdin" -@result{}0 -^D -@result{}#line 2 "stdin" -@result{}1 -@result{}#line 1 "stdin" -@result{}2 -@end example - -@comment FIXME - this needs to be fixed before 2.0. -The current @code{m4} implementation has a limitation that the syncline -output at the start of each diversion occurs no matter what, even if the -previous diversion did not end with a newline. This goes contrary to -the claim that synclines appear on a line by themselves, so this -limitation may be corrected in a future version of @code{m4}. In the -meantime, when using @option{-s}, it is wisest to make sure all -diversions end with newline. - -@item -GNU @code{m4} makes no attempt at prohibiting self-referential -definitions like: - -@comment ignore -@example -define(`x', `x') -@result{} -define(`x', `x ') -@result{} -@end example - -@cindex rescanning -There is nothing inherently wrong with defining @samp{x} to -return @samp{x}. The wrong thing is to expand @samp{x} unquoted, -because that would cause an infinite rescan loop. -In @code{m4}, one might use macros to hold strings, as we do for -variables in other programming languages, further checking them with: - -@comment ignore -@example -ifelse(defn(`@var{holder}'), `@var{value}', @dots{}) -@end example - -@noindent -In cases like this one, an interdiction for a macro to hold its own name -would be a useless limitation. Of course, this leaves more rope for the -GNU @code{m4} user to hang himself! Rescanning hangs may be -avoided through careful programming, a little like for endless loops in -traditional programming languages. - -@item -POSIX states that only unquoted leading newlines and blanks -(that is, space and tab) are ignored when collecting macro arguments. -However, this appears to be a bug in POSIX, since most -traditional implementations also ignore all whitespace (formfeed, -carriage return, and vertical tab). GNU @code{m4} follows -tradition and ignores all leading unquoted whitespace. -@end itemize - -@node Experiments -@section Experimental features in GNU M4 - -Certain features of GNU @code{m4} are experimental. - -Some are only available if activated by an option given to -@file{m4-@value{VERSION}/@/configure} at GNU @code{m4} installation -time. The functionality -might change or even go away in the future. @emph{Do not rely on it}. -Please direct your comments about it the same way you would do for bugs. - -@section Changesyntax - -An experimental feature, which improves the flexibility of @code{m4}, -allows for changing the way the input is parsed (@pxref{Changesyntax}). -No compile time option is needed for @code{changesyntax}. The -implementation is careful to not slow down @code{m4} parsing, unlike the -withdrawn experiment of @code{changeword} that appeared earlier in M4 -1.4.x. - -@section Multiple precision arithmetic - -Another experimental feature, which would improve @code{m4} usefulness, -allows for multiple precision rational arithmetic similar to -@code{eval}. You must have the GNU multi-precision (gmp) -library installed, and should use @kbd{./configure --with-gmp} if you -want this feature compiled in. The current implementation is unproven -and might go away. Do not count on it yet. - -@node Answers -@chapter Correct version of some examples - -Some of the examples in this manuals are buggy or not very robust, for -demonstration purposes. Improved versions of these composite macros are -presented here. - -@menu -* Improved exch:: Solution for @code{exch} -* Improved forloop:: Solution for @code{forloop} -* Improved foreach:: Solution for @code{foreach} -* Improved copy:: Solution for @code{copy} -* Improved m4wrap:: Solution for @code{m4wrap} -* Improved cleardivert:: Solution for @code{cleardivert} -* Improved capitalize:: Solution for @code{capitalize} -* Improved fatal_error:: Solution for @code{fatal_error} -@end menu - -@node Improved exch -@section Solution for @code{exch} - -The @code{exch} macro (@pxref{Arguments}) as presented requires clients -to double quote their arguments. A nicer definition, which lets -clients follow the rule of thumb of one level of quoting per level of -parentheses, involves adding quotes in the definition of @code{exch}, as -follows: - -@example -define(`exch', ``$2', `$1'') -@result{} -define(exch(`expansion text', `macro')) -@result{} -macro -@result{}expansion text -@end example - -@node Improved forloop -@section Solution for @code{forloop} - -The @code{forloop} macro (@pxref{Forloop}) as presented earlier can go -into an infinite loop if given an iterator that is not parsed as a macro -name. It does not do any sanity checking on its numeric bounds, and -only permits decimal numbers for bounds. Here is an improved version, -shipped as @file{m4-@value{VERSION}/@/doc/examples/@/forloop2.m4}; this -version also optimizes overhead by calling four macros instead of six -per iteration (excluding those in @var{text}), by not dereferencing the -@var{iterator} in the helper @code{@w{_forloop}}. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -undivert(`forloop2.m4')dnl -@result{}divert(`-1') -@result{}# forloop(var, from, to, stmt) - improved version: -@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 -@result{}define(`forloop', `ifelse(eval(`($2) <= ($3)'), `1', -@result{} `pushdef(`$1')_$0(`$1', eval(`$2'), -@result{} eval(`$3'), `$4')popdef(`$1')')') -@result{}define(`_forloop', -@result{} `define(`$1', `$2')$4`'ifelse(`$2', `$3', `', -@result{} `$0(`$1', incr(`$2'), `$3', `$4')')') -@result{}divert`'dnl -include(`forloop2.m4') -@result{} -forloop(`i', `2', `1', `no iteration occurs') -@result{} -forloop(`', `1', `2', ` odd iterator name') -@result{} odd iterator name odd iterator name -forloop(`i', `5 + 5', `0xc', ` 0x`'eval(i, `16')') -@result{} 0xa 0xb 0xc -forloop(`i', `a', `b', `non-numeric bounds') -@error{}m4:stdin:6: warning: eval: bad input: '(a) <= (b)' -@result{} -@end example - -One other change to notice is that the improved version used @samp{_$0} -rather than @samp{_foreach} to invoke the helper routine. In general, -this is a good practice to follow, because then the set of macros can be -uniformly transformed. The following example shows a transformation -that doubles the current quoting and appends a suffix @samp{2} to each -transformed macro. If @code{foreach} refers to the literal -@samp{_foreach}, then @code{foreach2} invokes @code{_foreach} instead of -the intended @code{_foreach2}, and the mixing of quoting paradigms leads -to an infinite recursion loop in this example. - -@comment options: -L9 -@comment status: 1 -@comment examples -@example -$ @kbd{m4 -d -L 9 -I doc/examples} -define(`arg1', `$1')include(`forloop2.m4')include(`quote.m4') -@result{} -define(`double', `define(`$1'`2', - arg1(patsubst(dquote(defn(`$1')), `[`']', `\&\&')))') -@result{} -double(`forloop')double(`_forloop')defn(`forloop2') -@result{}ifelse(eval(``($2) <= ($3)''), ``1'', -@result{} ``pushdef(``$1'')_$0(``$1'', eval(``$2''), -@result{} eval(``$3''), ``$4'')popdef(``$1'')'') -forloop(i, 1, 5, `ifelse(')forloop(i, 1, 5, `)') -@result{} -changequote(`[', `]')changequote([``], ['']) -@result{} -forloop2(i, 1, 5, ``ifelse('')forloop2(i, 1, 5, ``)'') -@result{} -changequote`'include(`forloop.m4') -@result{} -double(`forloop')double(`_forloop')defn(`forloop2') -@result{}pushdef(``$1'', ``$2'')_forloop($@@)popdef(``$1'') -forloop(i, 1, 5, `ifelse(')forloop(i, 1, 5, `)') -@result{} -changequote(`[', `]')changequote([``], ['']) -@result{} -forloop2(i, 1, 5, ``ifelse('')forloop2(i, 1, 5, ``)'') -@error{}m4:stdin:12: recursion limit of 9 exceeded, use -L to change it -@end example - -One more optimization is still possible. Instead of repeatedly -assigning a variable then invoking or dereferencing it, it is possible -to pass the current iterator value as a single argument. Coupled with -@code{curry} if other arguments are needed (@pxref{Composition}), or -with helper macros if the argument is needed in more than one place in -the expansion, the output can be generated with three, rather than four, -macros of overhead per iteration. Notice how the file -@file{m4-@value{VERSION}/@/doc/examples/@/forloop3.m4} rearranges the -arguments of the helper @code{_forloop} to take two arguments that are -placed around the current value. By splitting a balanced set of -parantheses across multiple arguments, the helper macro can now be -shared by @code{forloop} and the new @code{forloop_arg}. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`forloop3.m4') -@result{} -undivert(`forloop3.m4')dnl -@result{}divert(`-1') -@result{}# forloop_arg(from, to, macro) - invoke MACRO(value) for -@result{}# each value between FROM and TO, without define overhead -@result{}define(`forloop_arg', `ifelse(eval(`($1) <= ($2)'), `1', -@result{} `_forloop(`$1', eval(`$2'), `$3(', `)')')') -@result{}# forloop(var, from, to, stmt) - refactored to share code -@result{}define(`forloop', `ifelse(eval(`($2) <= ($3)'), `1', -@result{} `pushdef(`$1')_forloop(eval(`$2'), eval(`$3'), -@result{} `define(`$1',', `)$4')popdef(`$1')')') -@result{}define(`_forloop', -@result{} `$3`$1'$4`'ifelse(`$1', `$2', `', -@result{} `$0(incr(`$1'), `$2', `$3', `$4')')') -@result{}divert`'dnl -forloop(`i', `1', `3', ` i') -@result{} 1 2 3 -define(`echo', `$@@') -@result{} -forloop_arg(`1', `3', ` echo') -@result{} 1 2 3 -include(`curry.m4') -@result{} -forloop_arg(`1', `3', `curry(`pushdef', `a')') -@result{} -a -@result{}3 -popdef(`a')a -@result{}2 -popdef(`a')a -@result{}1 -popdef(`a')a -@result{}a -@end example - -Of course, it is possible to make even more improvements, such as -adding an optional step argument, or allowing iteration through -descending sequences. GNU Autoconf provides some of these -additional bells and whistles in its @code{m4_for} macro. - -@node Improved foreach -@section Solution for @code{foreach} - -The @code{foreach} and @code{foreachq} macros (@pxref{Foreach}) as -presented earlier each have flaws. First, we will examine and fix the -quadratic behavior of @code{foreachq}: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`foreachq.m4') -@result{} -traceon(`shift')debugmode(`aq') -@result{} -foreachq(`x', ``1', `2', `3', `4'', `x -')dnl -@result{}1 -@error{}m4trace: -3- shift(`1', `2', `3', `4') -@error{}m4trace: -2- shift(`1', `2', `3', `4') -@result{}2 -@error{}m4trace: -4- shift(`1', `2', `3', `4') -@error{}m4trace: -3- shift(`2', `3', `4') -@error{}m4trace: -3- shift(`1', `2', `3', `4') -@error{}m4trace: -2- shift(`2', `3', `4') -@result{}3 -@error{}m4trace: -5- shift(`1', `2', `3', `4') -@error{}m4trace: -4- shift(`2', `3', `4') -@error{}m4trace: -3- shift(`3', `4') -@error{}m4trace: -4- shift(`1', `2', `3', `4') -@error{}m4trace: -3- shift(`2', `3', `4') -@error{}m4trace: -2- shift(`3', `4') -@result{}4 -@error{}m4trace: -6- shift(`1', `2', `3', `4') -@error{}m4trace: -5- shift(`2', `3', `4') -@error{}m4trace: -4- shift(`3', `4') -@error{}m4trace: -3- shift(`4') -@end example - -@cindex quadratic behavior, avoiding -@cindex avoiding quadratic behavior -Each successive iteration was adding more quoted @code{shift} -invocations, and the entire list contents were passing through every -iteration. In general, when recursing, it is a good idea to make the -recursion use fewer arguments, rather than adding additional quoted -uses of @code{shift}. By doing so, @code{m4} uses less memory, invokes -fewer macros, is less likely to run into machine limits, and most -importantly, performs faster. The fixed version of @code{foreachq} can -be found in @file{m4-@value{VERSION}/@/doc/examples/@/foreachq2.m4}: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`foreachq2.m4') -@result{} -undivert(`foreachq2.m4')dnl -@result{}include(`quote.m4')dnl -@result{}divert(`-1') -@result{}# foreachq(x, `item_1, item_2, ..., item_n', stmt) -@result{}# quoted list, improved version -@result{}define(`foreachq', `pushdef(`$1')_$0($@@)popdef(`$1')') -@result{}define(`_arg1q', ``$1'') -@result{}define(`_rest', `ifelse(`$#', `1', `', `dquote(shift($@@))')') -@result{}define(`_foreachq', `ifelse(`$2', `', `', -@result{} `define(`$1', _arg1q($2))$3`'$0(`$1', _rest($2), `$3')')') -@result{}divert`'dnl -traceon(`shift')debugmode(`aq') -@result{} -foreachq(`x', ``1', `2', `3', `4'', `x -')dnl -@result{}1 -@error{}m4trace: -3- shift(`1', `2', `3', `4') -@result{}2 -@error{}m4trace: -3- shift(`2', `3', `4') -@result{}3 -@error{}m4trace: -3- shift(`3', `4') -@result{}4 -@end example - -Note that the fixed version calls unquoted helper macros in -@code{@w{_foreachq}} to trim elements immediately; those helper macros -in turn must re-supply the layer of quotes lost in the macro invocation. -Contrast the use of @code{@w{_arg1q}}, which quotes the first list -element, with @code{@w{_arg1}} of the earlier implementation that -returned the first list element directly. Additionally, by calling the -helper method immediately, the @samp{defn(`@var{iterator}')} no longer -contains unexpanded macros. - -The astute m4 programmer might notice that the solution above still uses -more macro invocations than strictly necessary. Note that @samp{$2}, -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 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 -@file{m4-@value{VERSION}/@/doc/examples/@/foreach3.m4}: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`foreachq3.m4') -@result{} -undivert(`foreachq3.m4')dnl -@result{}divert(`-1') -@result{}# foreachq(x, `item_1, item_2, ..., item_n', stmt) -@result{}# quoted list, alternate improved version -@result{}define(`foreachq', `ifelse(`$2', `', `', -@result{} `pushdef(`$1')_$0(`$1', `$3', `', $2)popdef(`$1')')') -@result{}define(`_foreachq', `ifelse(`$#', `3', `', -@result{} `define(`$1', `$4')$2`'$0(`$1', `$2', -@result{} shift(shift(shift($@@))))')') -@result{}divert`'dnl -traceon(`shift')debugmode(`aq') -@result{} -foreachq(`x', ``1', `2', `3', `4'', `x -')dnl -@result{}1 -@error{}m4trace: -4- shift(`x', `x -@error{}', `', `1', `2', `3', `4') -@error{}m4trace: -3- shift(`x -@error{}', `', `1', `2', `3', `4') -@error{}m4trace: -2- shift(`', `1', `2', `3', `4') -@result{}2 -@error{}m4trace: -4- shift(`x', `x -@error{}', `1', `2', `3', `4') -@error{}m4trace: -3- shift(`x -@error{}', `1', `2', `3', `4') -@error{}m4trace: -2- shift(`1', `2', `3', `4') -@result{}3 -@error{}m4trace: -4- shift(`x', `x -@error{}', `2', `3', `4') -@error{}m4trace: -3- shift(`x -@error{}', `2', `3', `4') -@error{}m4trace: -2- shift(`2', `3', `4') -@result{}4 -@error{}m4trace: -4- shift(`x', `x -@error{}', `3', `4') -@error{}m4trace: -3- shift(`x -@error{}', `3', `4') -@error{}m4trace: -2- shift(`3', `4') -@end example - -Prior to M4 1.6, every instance of @samp{$@@} was rescanned as it was -encountered. Thus, the @file{foreachq3.m4} alternative used much less -memory than @file{foreachq2.m4}, and executed as much as 10% faster, -since each iteration encountered fewer @samp{$@@}. However, the -implementation of rescanning every byte in @samp{$@@} was quadratic in -the number of bytes scanned (for example, making the broken version in -@file{foreachq.m4} cubic, rather than quadratic, in behavior). Once the -underlying M4 implementation was improved in 1.6 to reuse results of -previous scans, both styles of @code{foreachq} become linear in the -number of bytes scanned, but the @file{foreachq3.m4} version remains -noticeably faster because of fewer macro invocations. 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 -@code{shift}. Thus, each iteration only needs one @code{ifelse}, rather -than the two conditionals used in the version from @file{foreachq2.m4}. - -@cindex nine arguments, more than -@cindex more than nine arguments -@cindex 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 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 -@code{m4_define(`$1', `$@var{n}')$2`'}, with @samp{n} set to successive -integers corresponding to each argument. The helper macro -@code{_foreachq_} 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 -@code{shift} calls are even needed! However, when linear recursion is -available in new enough M4, the time and memory cost of using -@code{forloop} to build an intermediate macro outweigh the costs of any -of the previous implementations (there are seven macros of overhead per -iteration instead of six in @file{foreachq3.m4}, and the entire -intermediate macro must be built in memory before any iteration is -expanded). Additionally, this approach will need adjustment when a -future version of M4 follows POSIX by no longer treating -@samp{$10} as the tenth argument; the anticipation is that -@samp{$@{10@}} can be used instead, although that alternative syntax is -not yet supported. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`foreachq4.m4') -@result{} -undivert(`foreachq4.m4')dnl -@result{}include(`forloop2.m4')dnl -@result{}divert(`-1') -@result{}# foreachq(x, `item_1, item_2, ..., item_n', stmt) -@result{}# quoted list, version based on forloop -@result{}define(`foreachq', -@result{}`ifelse(`$2', `', `', `_$0(`$1', `$3', $2)')') -@result{}define(`_foreachq', -@result{}`pushdef(`$1', forloop(`$1', `3', `$#', -@result{} `$0_(`1', `2', indir(`$1'))')`popdef( -@result{} `$1')')indir(`$1', $@@)') -@result{}define(`_foreachq_', -@result{}``define(`$$1', `$$3')$$2`''') -@result{}divert`'dnl -traceon(`shift')debugmode(`aq') -@result{} -foreachq(`x', ``1', `2', `3', `4'', `x -')dnl -@result{}1 -@result{}2 -@result{}3 -@result{}4 -@end example - -For yet another approach, the improved version of @code{foreach}, -available in @file{m4-@value{VERSION}/@/doc/examples/@/foreach2.m4}, -simply overquotes the arguments to @code{@w{_foreach}} to begin with, -using @code{dquote_elt}. Then @code{@w{_foreach}} can just use -@code{@w{_arg1}} to remove the extra layer of quoting that was added up -front: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`foreach2.m4') -@result{} -undivert(`foreach2.m4')dnl -@result{}include(`quote.m4')dnl -@result{}divert(`-1') -@result{}# foreach(x, (item_1, item_2, ..., item_n), stmt) -@result{}# parenthesized list, improved version -@result{}define(`foreach', `pushdef(`$1')_$0(`$1', -@result{} (dquote(dquote_elt$2)), `$3')popdef(`$1')') -@result{}define(`_arg1', `$1') -@result{}define(`_foreach', `ifelse(`$2', `(`')', `', -@result{} `define(`$1', _arg1$2)$3`'$0(`$1', (dquote(shift$2)), `$3')')') -@result{}divert`'dnl -traceon(`shift')debugmode(`aq') -@result{} -foreach(`x', `(`1', `2', `3', `4')', `x -')dnl -@error{}m4trace: -4- shift(`1', `2', `3', `4') -@error{}m4trace: -4- shift(`2', `3', `4') -@error{}m4trace: -4- shift(`3', `4') -@result{}1 -@error{}m4trace: -3- shift(``1'', ``2'', ``3'', ``4'') -@result{}2 -@error{}m4trace: -3- shift(``2'', ``3'', ``4'') -@result{}3 -@error{}m4trace: -3- shift(``3'', ``4'') -@result{}4 -@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 -@code{_foreachq} as previously defined in @file{foreachq4.m4}. - -@cindex filtering defined symbols -@cindex subset of defined symbols -@cindex defined symbols, filtering -With a robust @code{foreachq} implementation, it is possible to create a -filter on a list of defined symbols. This next example will find all -symbols that contain @samp{if} or @samp{def}, via two different -approaches. In the first approach, @code{dquote_elt} is used to -overquote each list element, then @code{dquote} forms the list; that -way, the iterator @code{macro} can be expanded in place because its -contents are already quoted. This approach also uses a self-modifying -macro @code{sep} to provide the correct number of commas. In the second -approach, the iterator @code{macro} contains live text, so it must be -used with @code{defn} to avoid unintentional expansion. The correct -number of commas is achieved by using @code{shift} to ignore the first -one, although a leading space still remains. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`quote.m4')include(`foreachq2.m4') -@result{} -pushdef(`sep', `define(`sep', ``, '')') -@result{} -foreachq(`macro', dquote(dquote_elt(m4symbols)), - `regexp(macro, `.*if.*', `sep`\&'')') -@result{}ifdef, ifelse, shift -popdef(`sep') -@result{} -shift(foreachq(`macro', dquote(m4symbols), - `regexp(defn(`macro'), `def', `,` ''dquote(defn(`macro')))')) -@result{} define, defn, dumpdef, ifdef, popdef, pushdef, undefine -@end example - -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 -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 @code{@w{_foreach}}, similary for -@code{foreachq} as provided by @file{foreachq3.m4} or -@file{foreachq4.m4}. But -@code{foreachq}, as provided by @file{foreachq2.m4}, -evaluates unquoted list elements twice while visiting the first list -element, once in @code{@w{_arg1q}} and once in @code{@w{_rest}}. When -deciding which list style to use, one must take into account whether -repeating the side effects of unquoted list elements will have any -detrimental effects. - -@comment examples -@example -$ @kbd{m4 -d -I doc/examples} -include(`foreach2.m4') -@result{} -include(`foreachq2.m4') -@result{} -dnl 0-element list: -foreach(`x', `', `') / foreachq(`x', `', `') -@result{} /@w{ } -dnl 1-element list of empty element -foreach(`x', `()', `') / foreachq(`x', ``'', `') -@result{}<> / <> -dnl 2-element list of empty elements -foreach(`x', `(`',`')', `') / foreachq(`x', ``',`'', `') -@result{}<><> / <><> -dnl 1-element list of a comma -foreach(`x', `(`,')', `') / foreachq(`x', ``,'', `') -@result{}<,> / <,> -dnl 2-element list of unbalanced parentheses -foreach(`x', `(`(', `)')', `') / foreachq(`x', ``(', `)'', `') -@result{}<(><)> / <(><)> -define(`ab', `oops')dnl using defn(`iterator') -foreach(`x', `(`a', `b')', `defn(`x')') /dnl - foreachq(`x', ``a', `b'', `defn(`x')') -@result{}ab / ab -define(`active', `ACT, IVE') -@result{} -traceon(`active') -@result{} -dnl list of unquoted macros; expansion occurs before recursion -foreach(`x', `(active, active)', ` -')dnl -@error{}m4trace: -4- active -> `ACT, IVE' -@error{}m4trace: -4- active -> `ACT, IVE' -@result{} -@result{} -@result{} -@result{} -foreachq(`x', `active, active', ` -')dnl -@error{}m4trace: -3- active -> `ACT, IVE' -@error{}m4trace: -3- active -> `ACT, IVE' -@result{} -@error{}m4trace: -3- active -> `ACT, IVE' -@error{}m4trace: -3- active -> `ACT, IVE' -@result{} -@result{} -@result{} -dnl list of quoted macros; expansion occurs during recursion -foreach(`x', `(`active', `active')', ` -')dnl -@error{}m4trace: -1- active -> `ACT, IVE' -@result{} -@error{}m4trace: -1- active -> `ACT, IVE' -@result{} -foreachq(`x', ``active', `active'', ` -')dnl -@error{}m4trace: -1- active -> `ACT, IVE' -@result{} -@error{}m4trace: -1- active -> `ACT, IVE' -@result{} -dnl list of double-quoted macro names; no expansion -foreach(`x', `(``active'', ``active'')', ` -')dnl -@result{} -@result{} -foreachq(`x', ```active'', ``active''', ` -')dnl -@result{} -@result{} -@end example - -@node Improved copy -@section Solution for @code{copy} - -The macro @code{copy} presented above works with M4 1.6 and newer, but -is unable to handle builtin tokens with M4 1.4.x, because it tries to -pass the builtin token through the macro @code{curry}, where it is -silently flattened to an empty string (@pxref{Composition}). Rather -than using the problematic @code{curry} to work around the limitation -that @code{stack_foreach} expects to invoke a macro that takes exactly -one argument, we can write a new macro that lets us form the exact -two-argument @code{pushdef} call sequence needed, so that we are no -longer passing a builtin token through a text macro. - -@deffn Composite stack_foreach_sep (@var{macro}, @var{pre}, @var{post}, @ - @var{sep}) -@deffnx Composite stack_foreach_sep_lifo (@var{macro}, @var{pre}, @ - @var{post}, @var{sep}) -For each of the @code{pushdef} definitions associated with @var{macro}, -expand the sequence @samp{@var{pre}`'definition`'@var{post}}. -Additionally, expand @var{sep} between definitions. -@code{stack_foreach_sep} visits the oldest definition first, while -@code{stack_foreach_sep_lifo} visits the current definition first. The -expansion may dereference @var{macro}, but should not modify it. There -are a few special macros, such as @code{defn}, which cannot be used as -the @var{macro} parameter. -@end deffn - -Note that @code{stack_foreach(`@var{macro}', `@var{action}')} is -equivalent to @code{stack_foreach_sep(`@var{macro}', `@var{action}(', -`)')}. By supplying explicit parentheses, split among the @var{pre} and -@var{post} arguments to @code{stack_foreach_sep}, it is now possible to -construct macro calls with more than one argument, without passing -builtin tokens through a macro call. It is likewise possible to -directly reference the stack definitions without a macro call, by -leaving @var{pre} and @var{post} empty. Thus, in addition to fixing -@code{copy} on builtin tokens, it also executes with fewer macro -invocations. - -The new macro also adds a separator that is only output after the first -iteration of the helper @code{_stack_reverse_sep}, implemented by -prepending the original @var{sep} to @var{pre} and omitting a @var{sep} -argument in subsequent iterations. Note that the empty string that -separates @var{sep} from @var{pre} is provided as part of the fourth -argument when originally calling @code{_stack_reverse_sep}, and not by -writing @code{$4`'$3} as the third argument in the recursive call; while -the other approach would give the same output, it does so at the expense -of increasing the argument size on each iteration of -@code{_stack_reverse_sep}, which results in quadratic instead of linear -execution time. The improved stack walking macros are available in -@file{m4-@value{VERSION}/@/doc/examples/@/stack_sep.m4}: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`stack_sep.m4') -@result{} -define(`copy', `ifdef(`$2', `errprint(`$2 already defined -')m4exit(`1')', - `stack_foreach_sep(`$1', `pushdef(`$2',', `)')')')dnl -pushdef(`a', `1')pushdef(`a', defn(`divnum')) -@result{} -copy(`a', `b') -@result{} -b -@result{}0 -popdef(`b') -@result{} -b -@result{}1 -pushdef(`c', `1')pushdef(`c', `2') -@result{} -stack_foreach_sep_lifo(`c', `', `', `, ') -@result{}2, 1 -undivert(`stack_sep.m4')dnl -@result{}divert(`-1') -@result{}# stack_foreach_sep(macro, pre, post, sep) -@result{}# Invoke PRE`'defn`'POST with a single argument of each definition -@result{}# from the definition stack of MACRO, starting with the oldest, and -@result{}# separated by SEP between definitions. -@result{}define(`stack_foreach_sep', -@result{}`_stack_reverse_sep(`$1', `tmp-$1')'dnl -@result{}`_stack_reverse_sep(`tmp-$1', `$1', `$2`'defn(`$1')$3', `$4`'')') -@result{}# stack_foreach_sep_lifo(macro, pre, post, sep) -@result{}# Like stack_foreach_sep, but starting with the newest definition. -@result{}define(`stack_foreach_sep_lifo', -@result{}`_stack_reverse_sep(`$1', `tmp-$1', `$2`'defn(`$1')$3', `$4`'')'dnl -@result{}`_stack_reverse_sep(`tmp-$1', `$1')') -@result{}define(`_stack_reverse_sep', -@result{}`ifdef(`$1', `pushdef(`$2', defn(`$1'))$3`'popdef(`$1')$0( -@result{} `$1', `$2', `$4$3')')') -@result{}divert`'dnl -@end example - -@node Improved m4wrap -@section Solution for @code{m4wrap} - -The replacement @code{m4wrap} versions presented above, designed to -guarantee FIFO or LIFO order regardless of the underlying M4 -implementation, share a bug when dealing with wrapped text that looks -like parameter expansion. Note how the invocation of -@code{m4wrap@var{n}} interprets these parameters, while using the -builtin preserves them for their intended use. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`wraplifo.m4') -@result{} -m4wrap(`define(`foo', ``$0:'-$1-$*-$#-')foo(`a', `b') -') -@result{} -builtin(`m4wrap', ``'define(`bar', ``$0:'-$1-$*-$#-')bar(`a', `b') -') -@result{} -^D -@result{}m4wrap0:---0- -@result{}bar:-a-a,b-2- -@end example - -Additionally, the computation of @code{_m4wrap_level} and creation of -multiple @code{m4wrap@var{n}} placeholders in the original examples is -more expensive in time and memory than strictly necessary. Notice how -the improved version grabs the wrapped text via @code{defn} to avoid -parameter expansion, then undefines @code{_m4wrap_text}, before -stripping a level of quotes with @code{_arg1} to expand the text. That -way, each level of wrapping reuses the single placeholder, which starts -each nesting level in an undefined state. - -Finally, it is worth emulating the GNU M4 extension of saving -all arguments to @code{m4wrap}, separated by a space, rather than saving -just the first argument. This is done with the @code{join} macro -documented previously (@pxref{Shift}). The improved LIFO example is -shipped as @file{m4-@value{VERSION}/@/doc/examples/@/wraplifo2.m4}, and -can easily be converted to a FIFO solution by swapping the adjacent -invocations of @code{joinall} and @code{defn}. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`wraplifo2.m4') -@result{} -undivert(`wraplifo2.m4')dnl -@result{}dnl Redefine m4wrap to have LIFO semantics, improved example. -@result{}include(`join.m4')dnl -@result{}define(`_m4wrap', defn(`m4wrap'))dnl -@result{}define(`_arg1', `$1')dnl -@result{}define(`m4wrap', -@result{}`ifdef(`_$0_text', -@result{} `define(`_$0_text', joinall(` ', $@@)defn(`_$0_text'))', -@result{} `_$0(`_arg1(defn(`_$0_text')undefine(`_$0_text'))')dnl -@result{}define(`_$0_text', joinall(` ', $@@))')')dnl -m4wrap(`define(`foo', ``$0:'-$1-$*-$#-')foo(`a', `b') -') -@result{} -m4wrap(`lifo text -m4wrap(`nested', `', `$@@ -')') -@result{} -^D -@result{}lifo text -@result{}foo:-a-a,b-2- -@result{}nested $@@ -@end example - -@node Improved cleardivert -@section Solution for @code{cleardivert} - -The @code{cleardivert} macro (@pxref{Cleardivert}) cannot, as it stands, be -called without arguments to clear all pending diversions. That is -because using undivert with an empty string for an argument is different -than using it with no arguments at all. Compare the earlier definition -with one that takes the number of arguments into account: - -@example -define(`cleardivert', - `pushdef(`_n', divnum)divert(`-1')undivert($@@)divert(_n)popdef(`_n')') -@result{} -divert(`1')one -divert -@result{} -cleardivert -@result{} -undivert -@result{}one -@result{} -define(`cleardivert', - `pushdef(`_num', divnum)divert(`-1')ifelse(`$#', `0', - `undivert`'', `undivert($@@)')divert(_num)popdef(`_num')') -@result{} -divert(`2')two -divert -@result{} -cleardivert -@result{} -undivert -@result{} -@end example - -@node Improved capitalize -@section Solution for @code{capitalize} - -The @code{capitalize} macro (@pxref{Patsubst}) as presented earlier does -not allow clients to follow the quoting rule of thumb. Consider the -three macros @code{active}, @code{Active}, and @code{ACTIVE}, and the -difference between calling @code{capitalize} with the expansion of a -macro, expanding the result of a case change, and changing the case of a -double-quoted string: - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`capitalize.m4')dnl -define(`active', `act1, ive')dnl -define(`Active', `Act2, Ive')dnl -define(`ACTIVE', `ACT3, IVE')dnl -upcase(active) -@result{}ACT1,IVE -upcase(`active') -@result{}ACT3, IVE -upcase(``active'') -@result{}ACTIVE -downcase(ACTIVE) -@result{}act3,ive -downcase(`ACTIVE') -@result{}act1, ive -downcase(``ACTIVE'') -@result{}active -capitalize(active) -@result{}Act1 -capitalize(`active') -@result{}Active -capitalize(``active'') -@result{}_capitalize(`active') -define(`A', `OOPS') -@result{} -capitalize(active) -@result{}OOPSct1 -capitalize(`active') -@result{}OOPSctive -@end example - -First, when @code{capitalize} is called with more than one argument, it -was throwing away later arguments, whereas @code{upcase} and -@code{downcase} used @samp{$*} to collect them all. The fix is simple: -use @samp{$*} consistently. - -Next, with single-quoting, @code{capitalize} outputs a single character, -a set of quotes, then the rest of the characters, making it impossible -to invoke @code{Active} after the fact, and allowing the alternate macro -@code{A} to interfere. Here, the solution is to use additional quoting -in the helper macros, then pass the final over-quoted output string -through @code{_arg1} to remove the extra quoting and finally invoke the -concatenated portions as a single string. - -Finally, when passed a double-quoted string, the nested macro -@code{_capitalize} is never invoked because it ended up nested inside -quotes. This one is the toughest to fix. In short, we have no idea how -many levels of quotes are in effect on the substring being altered by -@code{patsubst}. If the replacement string cannot be expressed entirely -in terms of literal text and backslash substitutions, then we need a -mechanism to guarantee that the helper macros are invoked outside of -quotes. In other words, this sounds like a job for @code{changequote} -(@pxref{Changequote}). By changing the active quoting characters, we -can guarantee that replacement text injected by @code{patsubst} always -occurs in the middle of a string that has exactly one level of -over-quoting using alternate quotes; so the replacement text closes the -quoted string, invokes the helper macros, then reopens the quoted -string. In turn, that means the replacement text has unbalanced quotes, -necessitating another round of @code{changequote}. - -In the fixed version below, (also shipped as -@file{m4-@value{VERSION}/@/doc/examples/@/capitalize.m4}), -@code{capitalize} uses the alternate quotes of @samp{<<[} and @samp{]>>} -(the longer strings are chosen so as to be less likely to appear in the -text being converted). The helpers @code{_to_alt} and @code{_from_alt} -merely reduce the number of characters required to perform a -@code{changequote}, since the definition changes twice. The outermost -pair means that @code{patsubst} and @code{_capitalize_alt} are invoked -with alternate quoting; the innermost pair is used so that the third -argument to @code{patsubst} can contain an unbalanced -@samp{]>>}/@samp{<<[} pair. Note that @code{upcase} and @code{downcase} -must be redefined as @code{_upcase_alt} and @code{_downcase_alt}, since -they contain nested quotes but are invoked with the alternate quoting -scheme in effect. - -@comment examples -@example -$ @kbd{m4 -I doc/examples} -include(`capitalize2.m4')dnl -define(`active', `act1, ive')dnl -define(`Active', `Act2, Ive')dnl -define(`ACTIVE', `ACT3, IVE')dnl -define(`A', `OOPS')dnl -capitalize(active; `active'; ``active''; ```actIVE''') -@result{}Act1,Ive; Act2, Ive; Active; `Active' -undivert(`capitalize2.m4')dnl -@result{}divert(`-1') -@result{}# upcase(text) -@result{}# downcase(text) -@result{}# capitalize(text) -@result{}# change case of text, improved version -@result{}define(`upcase', `translit(`$*', `a-z', `A-Z')') -@result{}define(`downcase', `translit(`$*', `A-Z', `a-z')') -@result{}define(`_arg1', `$1') -@result{}define(`_to_alt', `changequote(`<<[', `]>>')') -@result{}define(`_from_alt', `changequote(<<[`]>>, <<[']>>)') -@result{}define(`_upcase_alt', `translit(<<[$*]>>, <<[a-z]>>, <<[A-Z]>>)') -@result{}define(`_downcase_alt', `translit(<<[$*]>>, <<[A-Z]>>, <<[a-z]>>)') -@result{}define(`_capitalize_alt', -@result{} `regexp(<<[$1]>>, <<[^\(\w\)\(\w*\)]>>, -@result{} <<[_upcase_alt(<<[<<[\1]>>]>>)_downcase_alt(<<[<<[\2]>>]>>)]>>)') -@result{}define(`capitalize', -@result{} `_arg1(_to_alt()patsubst(<<[<<[$*]>>]>>, <<[\w+]>>, -@result{} _from_alt()`]>>_$0_alt(<<[\&]>>)<<['_to_alt())_from_alt())') -@result{}divert`'dnl -@end example - -@node Improved fatal_error -@section Solution for @code{fatal_error} - -The @code{fatal_error} macro (@pxref{M4exit}) is not robust to versions -of GNU M4 earlier than 1.4.8, where invoking @code{@w{__file__}} -(@pxref{Location}) inside @code{m4wrap} would result in an empty string, -and @code{@w{__line__}} resulted in @samp{0} even though all files start -at line 1. Furthermore, versions earlier than 1.4.6 did not support the -@code{@w{__program__}} macro. If you want @code{fatal_error} to work -across the entire 1.4.x release series, a better implementation would -be: - -@comment status: 1 -@example -define(`fatal_error', - `errprint(ifdef(`__program__', `__program__', ``m4'')'dnl -`:ifelse(__line__, `0', `', - `__file__:__line__:')` fatal error: $* -')m4exit(`1')') -@result{} -m4wrap(`divnum(`demo of internal message') -fatal_error(`inside wrapped text')') -@result{} -^D -@error{}m4:stdin:6: warning: divnum: extra arguments ignored: 1 > 0 -@result{}0 -@error{}m4:stdin:6: fatal error: inside wrapped text -@end example - -@c ========================================================== Appendices - -@node Copying This Package -@appendix How to make copies of the overall M4 package -@cindex License, code - -This appendix covers the license for copying the source code of the -overall M4 package. This manual is under a different set of -restrictions, covered later (@pxref{Copying This Manual}). - -@menu -* GNU General Public License:: License for copying the M4 package -@end menu - -@node GNU General Public License -@appendixsec License for copying the M4 package -@cindex GPL, GNU General Public License -@cindex GNU General Public License -@cindex General Public License (GPL), GNU -@include gpl-3.0.texi - -@node Copying This Manual -@appendix How to make copies of this manual -@cindex License, manual - -This appendix covers the license for copying this manual. Note that -some of the longer examples in this manual are also distributed in the -directory @file{m4-@value{VERSION}/@/doc/examples/}, where a more -permissive license is in effect when copying just the examples. - -@menu -* GNU Free Documentation License:: License for copying this manual -@end menu - -@node GNU Free Documentation License -@appendixsec License for copying this manual -@cindex FDL, GNU Free Documentation License -@cindex GNU Free Documentation License -@cindex Free Documentation License (FDL), GNU -@include fdl-1.3.texi - -@node Indices -@appendix Indices of concepts and macros - -@menu -* Macro index:: Index for all @code{m4} macros -* Concept index:: Index for many concepts -@end menu - -@node Macro index -@appendixsec Index for all @code{m4} macros - -This index covers all @code{m4} builtins, as well as several useful -composite macros. References are exclusively to the places where a -macro is introduced the first time. - -@printindex fn - -@node Concept index -@appendixsec Index for many concepts - -@printindex cp - -@bye - -@c Local Variables: -@c fill-column: 72 -@c ispell-local-dictionary: "american" -@c indent-tabs-mode: nil -@c whitespace-check-buffer-indent: nil -@c End: diff --git a/m4/builtin.c b/m4/builtin.c deleted file mode 100644 index 19db0872..00000000 --- a/m4/builtin.c +++ /dev/null @@ -1,123 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 1999-2000, 2005-2008, 2010, 2013-2014, 2017 - 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 . -*/ - -/* Code for all builtin macros, initialisation of symbol table, and - expansion of user defined macros. */ - -#include - -#include "m4private.h" - -/* Comparison function, for use in bsearch, which compares NAME - against the name of BUILTIN. */ -static int -compare_builtin_name_CB (const void *name, const void *b) -{ - const m4__builtin *builtin = (const m4__builtin *) b; - return strcmp ((const char *) name, builtin->builtin.name); -} - -/* Find the builtin which has NAME. If MODULE is not NULL, then - search only in MODULE's builtin table. The result is a malloc'd - symbol value, suitable for use in the symbol table or for an - argument to m4_push_builtin. */ -m4_symbol_value * M4_GNUC_PURE -m4_builtin_find_by_name (m4 *context, m4_module *module, const char *name) -{ - m4_module *cur = module ? module : m4_module_next (context, NULL); - m4__builtin *bp; - - do - { - bp = (m4__builtin *) bsearch (name, cur->builtins, cur->builtins_len, - sizeof *bp, compare_builtin_name_CB); - if (bp) - { - m4_symbol_value *token = (m4_symbol_value *) xzalloc (sizeof *token); - m4__set_symbol_value_builtin (token, bp); - return token; - } - } - while (!module && (cur = m4_module_next (context, cur))); - - return NULL; -} - -/* Find the builtin which has FUNC. If MODULE argument is supplied - then search only in MODULE's builtin table. The result is a - malloc'd symbol value, suitable for use in the symbol table or for - an argument to m4_push_builtin. */ -m4_symbol_value * M4_GNUC_PURE -m4_builtin_find_by_func (m4 *context, m4_module *module, m4_builtin_func *func) -{ - m4_module *cur = module ? module : m4_module_next (context, NULL); - size_t i; - - do - { - for (i = 0; i < cur->builtins_len; i++) - if (cur->builtins[i].builtin.func == func) - { - m4_symbol_value *token = - (m4_symbol_value *) xzalloc (sizeof *token); - m4__set_symbol_value_builtin (token, &cur->builtins[i]); - return token; - } - } - while (!module && (cur = m4_module_next (context, cur))); - - return 0; -} - -/* Print a representation of FUNC to OBS, optionally including the - MODULE it came from. If FLATTEN, output QUOTES around an empty - string; if CHAIN, append the builtin to the chain; otherwise print - the name of FUNC. */ -void -m4__builtin_print (m4_obstack *obs, const m4__builtin *func, bool flatten, - m4__symbol_chain **chain, const m4_string_pair *quotes, - bool module) -{ - assert (func); - if (flatten) - { - if (quotes) - { - obstack_grow (obs, quotes->str1, quotes->len1); - obstack_grow (obs, quotes->str2, quotes->len2); - } - module = false; - } - else if (chain) - m4__append_builtin (obs, func, NULL, chain); - else - { - obstack_1grow (obs, '<'); - obstack_grow (obs, func->builtin.name, strlen (func->builtin.name)); - obstack_1grow (obs, '>'); - } - if (module) - { - const char *text = m4_get_module_name (func->module); - obstack_1grow (obs, '{'); - obstack_grow (obs, text, strlen (text)); - obstack_1grow (obs, '}'); - } -} diff --git a/m4/debug.c b/m4/debug.c deleted file mode 100644 index eb0e32fd..00000000 --- a/m4/debug.c +++ /dev/null @@ -1,260 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1991-1994, 2006-2010, 2013-2014, 2017 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 . -*/ - -#include - -#include -#include - -#include "m4private.h" -#include "close-stream.h" - -static void set_debug_file (m4 *, const m4_call_info *, FILE *); - - - -/* Function to decode the debugging flags OPTS of length LEN; or - SIZE_MAX if OPTS is NUL-terminated. If OPTS is NULL, use the - default flags. Used by main while processing option -d, and by the - builtin debugmode (). */ -int -m4_debug_decode (m4 *context, const char *opts, size_t len) -{ - int previous = context->debug_level; - int level; - char mode = '\0'; - - if (!opts) - opts = ""; - if (len == SIZE_MAX) - len = strlen (opts); - if (!len) - level = M4_DEBUG_TRACE_DEFAULT | previous; - else - { - if (*opts == '-' || *opts == '+') - { - len--; - mode = *opts++; - } - for (level = 0; len--; opts++) - { - switch (*opts) - { - case 'a': - level |= M4_DEBUG_TRACE_ARGS; - break; - - case 'e': - level |= M4_DEBUG_TRACE_EXPANSION; - break; - - case 'q': - level |= M4_DEBUG_TRACE_QUOTE; - break; - - case 't': - level |= M4_DEBUG_TRACE_ALL; - break; - - case 'l': - level |= M4_DEBUG_TRACE_LINE; - break; - - case 'f': - level |= M4_DEBUG_TRACE_FILE; - break; - - case 'p': - level |= M4_DEBUG_TRACE_PATH; - break; - - case 'c': - level |= M4_DEBUG_TRACE_CALL; - break; - - case 'i': - level |= M4_DEBUG_TRACE_INPUT; - break; - - case 'x': - level |= M4_DEBUG_TRACE_CALLID; - break; - - case 'm': - level |= M4_DEBUG_TRACE_MODULE; - break; - - case 's': - level |= M4_DEBUG_TRACE_STACK; - break; - - case 'd': - level |= M4_DEBUG_TRACE_DEREF; - break; - - case 'o': - level |= M4_DEBUG_TRACE_OUTPUT_DUMPDEF; - break; - - case 'V': - level |= M4_DEBUG_TRACE_VERBOSE; - break; - - default: - return -1; - } - } - } - - switch (mode) - { - case '\0': - /* Replace old level. */ - break; - - case '-': - /* Subtract flags. */ - level = previous & ~level; - break; - - case '+': - /* Add flags. */ - level |= previous; - break; - - default: - assert (!"m4_debug_decode"); - } - context->debug_level = level; - return level; -} - -/* Change the debug output stream to FP. If the underlying file is the - same as stdout, use stdout instead so that debug messages appear in the - correct relative position. Report errors on behalf of CALLER. */ -static void -set_debug_file (m4 *context, const m4_call_info *caller, FILE *fp) -{ - FILE *debug_file; - struct stat stdout_stat, debug_stat; - - assert (context); - - debug_file = m4_get_debug_file (context); - if (debug_file != NULL && debug_file != stderr && debug_file != stdout - && close_stream (debug_file) != 0) - m4_error (context, 0, errno, caller, _("error writing to debug stream")); - - debug_file = fp; - m4_set_debug_file (context, fp); - - if (debug_file != NULL && debug_file != stdout) - { - if (fstat (fileno (stdout), &stdout_stat) < 0) - return; - if (fstat (fileno (debug_file), &debug_stat) < 0) - return; - - /* mingw has a bug where fstat on a regular file reports st_ino - of 0. On normal system, st_ino should never be 0. */ - if (stdout_stat.st_ino == debug_stat.st_ino - && stdout_stat.st_dev == debug_stat.st_dev - && stdout_stat.st_ino != 0) - { - if (debug_file != stderr && close_stream (debug_file) != 0) - m4_error (context, 0, errno, caller, - _("error writing to debug stream")); - m4_set_debug_file (context, stdout); - } - } -} - -/* Change the debug output to file NAME. If NAME is NULL, debug - output is reverted to stderr, and if empty debug output is - discarded. Return true iff the output stream was changed. Report - errors on behalf of CALLER. */ -bool -m4_debug_set_output (m4 *context, const m4_call_info *caller, const char *name) -{ - FILE *fp; - - assert (context); - - if (name == NULL) - set_debug_file (context, caller, stderr); - else if (*name == '\0') - set_debug_file (context, caller, NULL); - else - { - fp = fopen (name, "a"); - if (fp == NULL) - return false; - - if (set_cloexec_flag (fileno (fp), true) != 0) - m4_warn (context, errno, caller, - _("cannot protect debug file across forks")); - set_debug_file (context, caller, fp); - } - return true; -} - -/* Print the header of a one-line debug message, starting with "m4debug:". */ -void -m4_debug_message_prefix (m4 *context) -{ - FILE *debug_file; - - assert (context); - - debug_file = m4_get_debug_file (context); - fputs ("m4debug:", debug_file); - if (m4_get_current_line (context)) - { - if (m4_is_debug_bit (context, M4_DEBUG_TRACE_FILE)) - xfprintf (debug_file, "%s:", m4_get_current_file (context)); - if (m4_is_debug_bit (context, M4_DEBUG_TRACE_LINE)) - xfprintf (debug_file, "%d:", m4_get_current_line (context)); - } - putc (' ', debug_file); -} - -/* If the current debug mode includes MODE, and there is a current - debug file, then output a debug message described by FORMAT. A - message header is supplied, as well as a trailing newline. */ -void -m4_debug_message (m4 *context, int mode, const char *format, ...) -{ - /* Check that mode has exactly one bit set. */ - assert (mode && (mode & (mode - 1)) == 0); - assert (format); - - if (m4_get_debug_file (context) != NULL - && m4_is_debug_bit (context, mode)) - { - va_list args; - - m4_debug_message_prefix (context); - va_start (args, format); - xvfprintf (m4_get_debug_file (context), format, args); - va_end (args); - putc ('\n', m4_get_debug_file (context)); - } -} diff --git a/m4/hash.c b/m4/hash.c deleted file mode 100644 index 01b90648..00000000 --- a/m4/hash.c +++ /dev/null @@ -1,671 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 2001, 2006-2010, 2013-2014, 2017 Free Software - Foundation, Inc. - Written by Gary V. Vaughan - - 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 . -*/ - -/* TODO: - - Use an obstack to manage the node memory. - - Implement the macroized magic values with the API. - */ - -#include - -#include "hash.h" -#include "m4private.h" - -#include "bitrotate.h" -#include - -typedef struct hash_node hash_node; - -struct m4_hash -{ - size_t size; /* number of buckets allocated */ - size_t length; /* number of elements inserted */ - m4_hash_hash_func *hash_func; - m4_hash_cmp_func *cmp_func; - hash_node **buckets; -#ifndef NDEBUG - m4_hash_iterator *iter; /* current iterator */ -#endif -}; - -struct hash_node -{ - hash_node *next; - const void *key; - void *value; -}; - - -struct m4_hash_iterator -{ - const m4_hash *hash; /* contains the buckets */ - hash_node * place; /* the node we are about to return */ - hash_node * next; /* the next node, incase PLACE is removed */ - size_t next_bucket; /* the next bucket index following NEXT */ -#ifndef NDEBUG - m4_hash_iterator *chain; /* multiple iterators visiting one hash */ -#endif -}; - - -#define HASH_SIZE(hash) ((hash)->size) -#define HASH_LENGTH(hash) ((hash)->length) -#define HASH_BUCKETS(hash) ((hash)->buckets) -#define HASH_HASH_FUNC(hash) ((hash)->hash_func) -#define HASH_CMP_FUNC(hash) ((hash)->cmp_func) - -#define NODE_NEXT(node) ((node)->next) -#define NODE_KEY(node) ((node)->key) -#define NODE_VALUE(node) ((node)->value) - -#define ITERATOR_HASH(i) ((i)->hash) -#define ITERATOR_PLACE(i) ((i)->place) -#define ITERATOR_NEXT(i) ((i)->next) -#define ITERATOR_NEXT_BUCKET(i) ((i)->next_bucket) - -/*#define ITERATOR_NEXT_NEXT(i) NODE_NEXT (ITERATOR_PLACE (i))*/ - -/* Helper macros. */ -#define BUCKET_NTH(hash, n) (HASH_BUCKETS (hash)[n]) -#define BUCKET_COUNT(hash, key) \ - ((*HASH_HASH_FUNC (hash))(key) % HASH_SIZE (hash)) -#define BUCKET_KEY(hash, key) \ - (BUCKET_NTH ((hash), BUCKET_COUNT ((hash), (key)))) - -/* Debugging macros. */ -#ifdef NDEBUG -# define HASH_ITER(hash) 0 -# define ITER_CHAIN(iter) 0 -#else -# define HASH_ITER(hash) (((m4_hash *) hash)->iter) -# define ITER_CHAIN(iter) ((iter)->chain) -#endif - - -static void bucket_insert (m4_hash *hash, hash_node *bucket); -static void bucket_delete (m4_hash *hash, size_t i); -static hash_node * node_new (const void *key, void *value); -static void node_insert (m4_hash *hash, hash_node *node); -static hash_node * node_lookup (m4_hash *hash, const void *key); -static void node_delete (m4_hash *hash, hash_node *node); -static void maybe_grow (m4_hash *hash); - - - -static hash_node *free_list = NULL; - - - -/* Allocate and return a new, unpopulated but initialised m4_hash with - SIZE buckets, where HASH_FUNC will be used to generate bucket numbers - and CMP_FUNC will be called to compare keys. */ -m4_hash * -m4_hash_new (size_t size, m4_hash_hash_func *hash_func, - m4_hash_cmp_func *cmp_func) -{ - m4_hash *hash; - - assert (hash_func); - assert (cmp_func); - - if (size == 0) - size = M4_HASH_DEFAULT_SIZE; - - hash = (m4_hash *) xmalloc (sizeof *hash); - HASH_SIZE (hash) = size; - HASH_LENGTH (hash) = 0; - HASH_BUCKETS (hash) = (hash_node **) xcalloc (size, - sizeof *HASH_BUCKETS (hash)); - HASH_HASH_FUNC (hash) = hash_func; - HASH_CMP_FUNC (hash) = cmp_func; -#ifndef NDEBUG - HASH_ITER (hash) = NULL; -#endif - - return hash; -} - -m4_hash * -m4_hash_dup (m4_hash *src, m4_hash_copy_func *copy) -{ - m4_hash *dest; - - assert (src); - assert (copy); - - dest = m4_hash_new (HASH_SIZE (src), HASH_HASH_FUNC (src), - HASH_CMP_FUNC (src)); - - m4_hash_apply (src, (m4_hash_apply_func *) copy, dest); - - return dest; -} - -/* Recycle each of the nodes in HASH onto the free list, and release - the rest of the memory used by the table. Memory addressed by the - recycled nodes is _NOT_ freed: this needs to be done manually to - prevent memory leaks. This is not safe to call while HASH is being - iterated. */ -void -m4_hash_delete (m4_hash *hash) -{ - size_t i; - - assert (hash); - assert (!HASH_ITER (hash)); - - for (i = 0; i < HASH_SIZE (hash); ++i) - if (BUCKET_NTH (hash, i)) - bucket_delete (hash, i); - free (HASH_BUCKETS (hash)); - free (hash); -} - -/* Check that the nodes in bucket I have been cleared, and recycle - each of the nodes in the bucket to the free list. Bucket I must - not be empty when this function is called. */ -static void -bucket_delete (m4_hash *hash, size_t i) -{ - hash_node *node; - - assert (hash); - assert (BUCKET_NTH (hash, i)); - assert (i < HASH_SIZE (hash)); - - for (node = BUCKET_NTH (hash, i); node->next; node = NODE_NEXT (node)) - { - assert (NODE_KEY (node) == NULL); - --HASH_LENGTH (hash); - } - - assert (NODE_KEY (node) == NULL); - --HASH_LENGTH (hash); - - NODE_NEXT (node) = free_list; - free_list = BUCKET_NTH (hash, i); - BUCKET_NTH (hash, i) = NULL; -} - -/* Create and initialise a new node with KEY and VALUE, by reusing a - node from the free list if possible. */ -static hash_node * -node_new (const void *key, void *value) -{ - hash_node *node = NULL; - - if (free_list) - { - node = free_list; - free_list = NODE_NEXT (free_list); - } - else - node = (hash_node *) xmalloc (sizeof *node); - - assert (node); - - NODE_NEXT (node) = NULL; - NODE_KEY (node) = key; - NODE_VALUE (node) = value; - - return node; -} - -/* Check that NODE has been cleared, and recycle it to the free list. */ -static void -node_delete (m4_hash *hash, hash_node *node) -{ - assert (node); - assert (NODE_KEY (node) == NULL); - - NODE_NEXT (node) = free_list; - free_list = node; - - --HASH_LENGTH (hash); -} - -/* Create a new entry in HASH with KEY and VALUE, making use of nodes - in the free list if possible, and potentially growing the size of - the table if node density is too high. This is not safe to call - while HASH is being iterated. Currently, it is not safe to call - this if another entry already matches KEY. */ -const void * -m4_hash_insert (m4_hash *hash, const void *key, void *value) -{ - hash_node *node; - - assert (hash); - assert (!HASH_ITER (hash)); - - node = node_new (key, value); - node_insert (hash, node); - maybe_grow (hash); - - return key; -} - -/* Push the unconnected NODE on to the front of the appropriate - bucket, effectively preventing retrieval of other nodes with - the same key (where "sameness" is determined by HASH's - cmp_func). */ -static void -node_insert (m4_hash *hash, hash_node *node) -{ - size_t n; - - assert (hash); - assert (node); - assert (NODE_NEXT (node) == NULL); - - n = BUCKET_COUNT (hash, NODE_KEY (node)); - NODE_NEXT (node) = BUCKET_NTH (hash, n); - BUCKET_NTH (hash, n) = node; - - ++HASH_LENGTH (hash); -} - -/* Remove from HASH, the first node with key KEY; comparing keys with - HASH's cmp_func. Any nodes with the same KEY previously hidden by - the removed node will become visible again. The key field of the - removed node is returned, or NULL if there was no match. This is - unsafe if multiple iterators are visiting HASH, or when a lone - iterator is visiting on a different key. */ -void * -m4_hash_remove (m4_hash *hash, const void *key) -{ - size_t n; - hash_node *node = NULL; - -#ifndef NDEBUG - m4_hash_iterator *iter = HASH_ITER (hash); - - assert (hash); - if (HASH_ITER (hash)) - { - assert (!ITER_CHAIN (iter)); - assert (ITERATOR_PLACE (iter)); - } -#endif - - n = BUCKET_COUNT (hash, key); - do - { - hash_node *next = node ? NODE_NEXT (node) : BUCKET_NTH (hash, n); - - if (next && ((*HASH_CMP_FUNC (hash)) (NODE_KEY (next), key) == 0)) - { - if (node) - NODE_NEXT (node) = NODE_NEXT (next); - else - BUCKET_NTH (hash, n) = NODE_NEXT (next); - - key = NODE_KEY (next); -#ifndef NDEBUG - if (iter) - assert (ITERATOR_PLACE (iter) == next); - NODE_KEY (next) = NULL; -#endif - node_delete (hash, next); - return (void *) key; /* Cast away const. */ - } - node = next; - } - while (node); - - return NULL; -} - -/* Return the address of the value field of the first node in HASH - that has a matching KEY. The address is returned so that an - explicit NULL value can be distinguished from a failed lookup (also - NULL). Fortuitously for M4, this also means that the value field - can be changed `in situ' to implement a value stack. Safe to call - even when an iterator is in force. */ -void ** -m4_hash_lookup (m4_hash *hash, const void *key) -{ - hash_node *node; - - assert (hash); - - node = node_lookup (hash, key); - - return node ? &NODE_VALUE (node) : NULL; -} - -/* Return the first node in HASH that has a matching KEY. */ -static hash_node * -node_lookup (m4_hash *hash, const void *key) -{ - hash_node *node; - - assert (hash); - - node = BUCKET_KEY (hash, key); - - while (node && (*HASH_CMP_FUNC (hash)) (NODE_KEY (node), key)) - node = NODE_NEXT (node); - - return node; -} - -/* How many entries are currently contained by HASH. Safe to call - even during an interation. */ -size_t M4_GNUC_PURE -m4_get_hash_length (m4_hash *hash) -{ - assert (hash); - - return HASH_LENGTH (hash); -} - -#if 0 -/* Force the number of buckets to be the given value. You probably ought - not to be using this function once the table has been in use, since - the maximum density algorithm will grow the number of buckets back to - what was there before if you try to shrink the table. It is useful - to set a smaller or larger initial size if you know in advance what - order of magnitude of entries will be in the table. Be aware that - the efficiency of the lookup and grow features require that the size - always be 1 less than a power of 2. Unsafe if HASH is being visited - by an iterator. */ -void -m4_hash_resize (m4_hash *hash, size_t size) -{ - hash_node **original_buckets; - size_t original_size; - - assert (hash); - assert (!HASH_ITER (hash)); - - original_size = HASH_SIZE (hash); - original_buckets = HASH_BUCKETS (hash); - - HASH_SIZE (hash) = size; - HASH_BUCKETS (hash) = (hash_node **) xcalloc (size, - sizeof *HASH_BUCKETS (hash)); - - { - size_t i; - for (i = 0; i < original_size; ++i) - if (original_buckets[i]) - bucket_insert (hash, original_buckets[i]); - } - - free (original_buckets); -} -#endif - -/* If the node density breaks the threshold, increase the size of - HASH and repopulate with the original nodes. */ -static void -maybe_grow (m4_hash *hash) -{ - float nodes_per_bucket; - - assert (hash); - - nodes_per_bucket = (float) HASH_LENGTH (hash) / (float) HASH_SIZE (hash); - - if (nodes_per_bucket > (float) M4_HASH_MAXIMUM_DENSITY) - { - size_t original_size = HASH_SIZE (hash); - hash_node **original_buckets = HASH_BUCKETS (hash); - - /* HASH sizes are always 1 less than a power of 2. */ - HASH_SIZE (hash) = (2 * (1 + original_size)) -1; - HASH_BUCKETS (hash) = - (hash_node **) xcalloc (HASH_SIZE (hash), sizeof *HASH_BUCKETS (hash)); - - { - size_t i; - for (i = 0; i < original_size; ++i) - if (original_buckets[i]) - bucket_insert (hash, original_buckets[i]); - } - - free (original_buckets); - } -} - -/* Insert each node in BUCKET into HASH. Relative ordering of nodes - is not preserved. This would need to change if we were to - guarantee relative ordering within a bucket for identical keys. */ -static void -bucket_insert (m4_hash *hash, hash_node *bucket) -{ - assert (hash); - assert (bucket); - - do - { - hash_node *next = NODE_NEXT (bucket); - - /* Break link to rest of the bucket before reinserting. */ - NODE_NEXT (bucket) = NULL; - node_insert (hash, bucket); - - bucket = next; - } - while (bucket); -} - -/* Reclaim all memory used by free nodes. Safe to call at any time, - although only worth calling at program shutdown to verify no - leaks. */ -void -m4_hash_exit (void) -{ - while (free_list) - { - hash_node *stale = free_list; - free_list = NODE_NEXT (stale); - free (stale); - } -} - - - -/* Iterate over a given HASH. Start with PLACE being NULL, then - repeat with PLACE being the previous return value. The return - value is the current location of the iterator, or NULL when the - walk is complete. Call m4_free_hash_iterator to abort iteration. - During the iteration, it is safe to search the list, and if no - other iterator is active, it is safe to remove the key pointed to - by this iterator. All other actions that modify HASH are - unsafe. */ -m4_hash_iterator * -m4_get_hash_iterator_next (const m4_hash *hash, m4_hash_iterator *place) -{ - assert (hash); - assert (!place || (ITERATOR_HASH (place) == hash)); - - /* On the first iteration, allocate an iterator. */ - if (!place) - { - place = (m4_hash_iterator *) xzalloc (sizeof *place); - ITERATOR_HASH (place) = hash; -#ifndef NDEBUG - ITER_CHAIN (place) = HASH_ITER (hash); - HASH_ITER (hash) = place; -#endif - } - - next: - ITERATOR_PLACE (place) = ITERATOR_NEXT (place); - - /* If there is another node in the current bucket, select it. */ - if (ITERATOR_NEXT (place) && NODE_NEXT (ITERATOR_NEXT (place))) - { - ITERATOR_NEXT (place) = NODE_NEXT (ITERATOR_NEXT (place)); - } - else - { - /* Find the next non-empty bucket. */ - while ((ITERATOR_NEXT_BUCKET (place) < HASH_SIZE (hash)) - && (BUCKET_NTH (hash, ITERATOR_NEXT_BUCKET (place)) == NULL)) - { - ++ITERATOR_NEXT_BUCKET (place); - } - - /* Select the first node in the new bucket. */ - if (ITERATOR_NEXT_BUCKET (place) < HASH_SIZE (hash)) - { - ITERATOR_NEXT (place) - = BUCKET_NTH (hash, ITERATOR_NEXT_BUCKET (place)); - } - else - ITERATOR_NEXT (place) = NULL; - - /* Advance the `next' reference. */ - ++ITERATOR_NEXT_BUCKET (place); - } - - /* If there are no more nodes to return, recycle the iterator memory. */ - if (! (ITERATOR_PLACE (place) || ITERATOR_NEXT (place))) - { - m4_free_hash_iterator (hash, place); - return NULL; - } - - /* On the first call we need to put the 1st node in PLACE and - the 2nd node in NEXT. */ - if (ITERATOR_NEXT (place) && !ITERATOR_PLACE (place)) - goto next; - - assert (place && ITERATOR_PLACE (place)); - - return place; -} - -/* Clean up the iterator PLACE within HASH when aborting an iteration - early. */ -void -m4_free_hash_iterator (const m4_hash *hash, m4_hash_iterator *place) -{ -#ifndef NDEBUG - m4_hash_iterator *iter = NULL; - m4_hash_iterator *next; - - assert (hash); - assert (place && (ITERATOR_HASH (place) == hash)); - - do - { - next = iter ? ITER_CHAIN (iter) : HASH_ITER (hash); - if (place == next) - { - if (iter) - ITER_CHAIN (iter) = ITER_CHAIN (next); - else - HASH_ITER (hash) = ITER_CHAIN (next); - break; - } - iter = next; - } - while (iter); - assert (next); -#endif - free (place); -} - -/* Return the key being visited by the iterator PLACE. */ -const void * M4_GNUC_PURE -m4_get_hash_iterator_key (m4_hash_iterator *place) -{ - assert (place); - - return NODE_KEY (ITERATOR_PLACE (place)); -} - -/* Return the value being visited by the iterator PLACE. */ -void * M4_GNUC_PURE -m4_get_hash_iterator_value (m4_hash_iterator *place) -{ - assert (place); - - return NODE_VALUE (ITERATOR_PLACE (place)); -} - -/* The following function is used for the cases where we want to do - something to each and every entry in HASH. This function traverses - the hash table, and calls a specified function FUNC for each entry - in the table. FUNC is called with a pointer to the entry key, - value, and the passed DATA argument. If FUNC returns non-NULL, - abort the iteration and return that value; a return of NULL implies - success on all entries. */ -void * -m4_hash_apply (m4_hash *hash, m4_hash_apply_func *func, void *userdata) -{ - m4_hash_iterator *place = NULL; - void * result = NULL; - - assert (hash); - assert (func); - - while ((place = m4_get_hash_iterator_next (hash, place))) - { - result = (*func) (hash, m4_get_hash_iterator_key (place), - m4_get_hash_iterator_value (place), userdata); - - if (result != NULL) - { - m4_free_hash_iterator (hash, place); - break; - } - } - - return result; -} - - -/* Using a string (char * and size_t pair) as the hash key is common - enough that we provide implementations here for use in client hash - table routines. */ - -/* Return a hash value for a string, similar to gnulib's hash module, - but with length factored in. */ -size_t M4_GNUC_PURE -m4_hash_string_hash (const void *ptr) -{ - const m4_string *key = (const m4_string *) ptr; - const char *s = key->str; - size_t len = key->len; - size_t val = len; - - while (len--) - val = rotl_sz (val, 7) + to_uchar (*s++); - return val; -} - -/* Comparison function for hash keys -- used by the underlying - hash table ADT when searching for a key match during name lookup. */ -int M4_GNUC_PURE -m4_hash_string_cmp (const void *key, const void *try) -{ - const m4_string *a = (const m4_string *) key; - const m4_string *b = (const m4_string *) try; - if (a->len < b->len) - return -1; - if (b->len < a->len) - return 1; - return memcmp (a->str, b->str, a->len); -} diff --git a/m4/hash.h b/m4/hash.h deleted file mode 100644 index 46f0eeeb..00000000 --- a/m4/hash.h +++ /dev/null @@ -1,81 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 2001, 2006-2007, 2010, 2013-2014, 2017 Free Software - Foundation, Inc. - Written by Gary V. Vaughan - - 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 . -*/ - -#ifndef M4_HASH_H -#define M4_HASH_H 1 - -#include - -/* Must be 1 less than a power of 2 for the resize algorithm to - be efficient. */ -#define M4_HASH_DEFAULT_SIZE 511 - -/* When the average number of values per bucket breaks this value - the table will be grown to reduce the density accordingly. */ -#define M4_HASH_MAXIMUM_DENSITY 3.0 - -BEGIN_C_DECLS - -typedef struct m4_hash m4_hash; - -typedef size_t m4_hash_hash_func (const void *key); -typedef int m4_hash_cmp_func (const void *key, const void *try); -typedef void * m4_hash_copy_func (m4_hash *src, const void *key, void *value, - m4_hash *dest); - -extern m4_hash *m4_hash_new (size_t size, m4_hash_hash_func *hash_func, - m4_hash_cmp_func *cmp_func); -extern m4_hash *m4_hash_dup (m4_hash *hash, m4_hash_copy_func *copy); -extern void m4_hash_delete (m4_hash *hash); -extern void m4_hash_exit (void); - -extern size_t m4_get_hash_length (m4_hash *hash); - -extern void ** m4_hash_lookup (m4_hash *hash, const void *key); -extern void * m4_hash_remove (m4_hash *hash, const void *key); -extern const void * m4_hash_insert (m4_hash *hash, const void *key, - void *value); - - - -extern size_t m4_hash_string_hash (const void *key); -extern int m4_hash_string_cmp (const void *key, const void *try); - - - -typedef struct m4_hash_iterator m4_hash_iterator; -typedef void * m4_hash_apply_func (m4_hash *hash, const void *key, - void *value, void *userdata); - -extern void * m4_hash_apply (m4_hash *hash, m4_hash_apply_func *func, - void *userdata); - -extern const void * m4_get_hash_iterator_key (m4_hash_iterator *place); -extern void * m4_get_hash_iterator_value (m4_hash_iterator *place); -extern m4_hash_iterator *m4_get_hash_iterator_next (const m4_hash *hash, - m4_hash_iterator *place); -extern void m4_free_hash_iterator (const m4_hash *hash, - m4_hash_iterator *place); - - -END_C_DECLS - -#endif /* !M4_HASH_H */ diff --git a/m4/input.c b/m4/input.c deleted file mode 100644 index edce12e4..00000000 --- a/m4/input.c +++ /dev/null @@ -1,2223 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 2006-2010, 2013-2014, 2017 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 . -*/ - -/* Handling of different input sources, and lexical analysis. */ - -#include - -#include "m4private.h" - -#include "freadptr.h" -#include "freadseek.h" -#include "memchr2.h" - -/* Define this to see runtime debug info. Implied by DEBUG. */ -/*#define DEBUG_INPUT */ - -/* Maximum number of bytes where it is more efficient to inline the - reference as a string than it is to track reference bookkeeping for - those bytes. */ -#define INPUT_INLINE_THRESHOLD 16 - -/* - Unread input can be either files that should be read (from the - command line or by include/sinclude), strings which should be - rescanned (normal macro expansion text), or quoted builtin - definitions (as returned by the builtin "defn"). Unread input is - organized in a stack, implemented with an obstack. Each input - source is described by a "struct m4_input_block". The obstack is - "input_stack". The top of the input stack is "isp". - - Each input_block has an associated struct input_funcs, which is a - vtable that defines polymorphic functions for peeking, reading, - unget, cleanup, and printing in trace output. Getting a single - character at a time is inefficient, so there are also functions for - accessing the readahead buffer and consuming bulk input. All input - is done through the function pointers of the input_funcs on the - given input_block, and all characters are unsigned, to distinguish - between stdio EOF and between special sentinel characters. When a - input_block is exhausted, its reader returns CHAR_RETRY which - causes the input_block to be popped from the input_stack. - - The macro "m4wrap" places the text to be saved on another input - stack, on the obstack "wrapup_stack", whose top is "wsp". When EOF - is seen on normal input (eg, when "current_input" is empty), input - is switched over to "wrapup_stack", and the original - "current_input" is freed. A new stack is allocated for - "wrapup_stack", which will accept any text produced by calls to - "m4wrap" from within the wrapped text. This process of shuffling - "wrapup_stack" to "current_input" can continue indefinitely, even - generating infinite loops (e.g. "define(`f',`m4wrap(`f')')f"), - without memory leaks. Adding wrapped data is done through - m4__push_wrapup_init/m4__push_wrapup_finish(). - - Pushing new input on the input stack is done by m4_push_file(), the - conceptual m4_push_string(), and m4_push_builtin() (for builtin - definitions). As an optimization, since most macro expansions - result in strings, m4_push_string() is split in two parts, - push_string_init(), which returns a pointer to the obstack for - growing the output, and push_string_finish(), which returns a - pointer to the finished input_block. Thus, instead of creating a - new input block for every character pushed, macro expansion need - only add text to the top of the obstack. However, it is not safe - to alter the input stack while a string is being constructed. This - means the input engine is one of two states: consuming input, or - collecting a macro's expansion. The input_block *next is used to - manage the coordination between the different push routines. - - Normally, input sources behave in LIFO order, resembling a stack. - But thanks to the defn and m4wrap macros, when collecting the - expansion of a macro, it is possible that we must intermix multiple - input blocks in FIFO order. Therefore, when collecting an - expansion, a meta-input block is formed which will visit its - children in FIFO order, without losing data when the obstack is - cleared in LIFO order. - - The current file and line number are stored in the context, for use - by the error handling functions in utility.c. When collecting a - macro's expansion, these variables can be temporarily inconsistent - in order to provide better error message locations, but they must - be restored before further parsing takes place. Each input block - maintains its own notion of the current file and line, so swapping - between input blocks must update the context accordingly. */ - -typedef struct m4_input_block m4_input_block; - -static int file_peek (m4_input_block *, m4 *, bool); -static int file_read (m4_input_block *, m4 *, bool, bool, - bool); -static void file_unget (m4_input_block *, int); -static bool file_clean (m4_input_block *, m4 *, bool); -static void file_print (m4_input_block *, m4 *, m4_obstack *, - int); -static const char * file_buffer (m4_input_block *, m4 *, size_t *, - bool); -static void file_consume (m4_input_block *, m4 *, size_t); -static int string_peek (m4_input_block *, m4 *, bool); -static int string_read (m4_input_block *, m4 *, bool, bool, - bool); -static void string_unget (m4_input_block *, int); -static void string_print (m4_input_block *, m4 *, m4_obstack *, - int); -static const char * string_buffer (m4_input_block *, m4 *, size_t *, - bool); -static void string_consume (m4_input_block *, m4 *, size_t); -static int composite_peek (m4_input_block *, m4 *, bool); -static int composite_read (m4_input_block *, m4 *, bool, bool, - bool); -static void composite_unget (m4_input_block *, int); -static bool composite_clean (m4_input_block *, m4 *, bool); -static void composite_print (m4_input_block *, m4 *, m4_obstack *, - int); -static const char * composite_buffer (m4_input_block *, m4 *, size_t *, - bool); -static void composite_consume (m4_input_block *, m4 *, size_t); -static int eof_peek (m4_input_block *, m4 *, bool); -static int eof_read (m4_input_block *, m4 *, bool, bool, - bool); -static void eof_unget (m4_input_block *, int); -static const char * eof_buffer (m4_input_block *, m4 *, size_t *, - bool); - -static void init_builtin_token (m4 *, m4_obstack *, - m4_symbol_value *); -static void append_quote_token (m4 *, m4_obstack *, - m4_symbol_value *); -static bool match_input (m4 *, const char *, size_t, bool); -static int next_char (m4 *, bool, bool, bool); -static int peek_char (m4 *, bool); -static bool pop_input (m4 *, bool); -static void unget_input (int); -static const char * next_buffer (m4 *, size_t *, bool); -static void consume_buffer (m4 *, size_t); -static bool consume_syntax (m4 *, m4_obstack *, unsigned int); - -#ifdef DEBUG_INPUT -# include "quotearg.h" - -static int m4_print_token (m4 *, const char *, m4__token_type, - m4_symbol_value *); -#endif - -/* Vtable of callbacks for each input method. */ -struct input_funcs -{ - /* Peek at input, return an unsigned char, CHAR_BUILTIN if it is a - builtin, or CHAR_RETRY if none available. If ALLOW_ARGV, then - CHAR_ARGV may be returned. */ - int (*peek_func) (m4_input_block *, m4 *, bool); - - /* Read input, return an unsigned char, CHAR_BUILTIN if it is a - builtin, or CHAR_RETRY if none available. If ALLOW_QUOTE, then - CHAR_QUOTE may be returned. If ALLOW_ARGV, then CHAR_ARGV may be - returned. If ALLOW_UNGET, then ensure that the next unget_func - will work with the returned character. */ - int (*read_func) (m4_input_block *, m4 *, bool allow_quote, - bool allow_argv, bool allow_unget); - - /* Unread a single unsigned character or CHAR_BUILTIN, must be the - same character previously read by read_func. */ - void (*unget_func) (m4_input_block *, int); - - /* Optional function to perform cleanup at end of input. If - CLEANUP, it is safe to perform non-recoverable cleanup actions. - Return true only if no cleanup remains to be done. */ - bool (*clean_func) (m4_input_block *, m4 *, bool cleanup); - - /* Add a representation of the input block to the obstack, for use - in trace expansion output. */ - void (*print_func) (m4_input_block *, m4 *, m4_obstack *, int); - - /* Return a pointer to the current readahead buffer, and set LEN to - the length of the result. If ALLOW_QUOTE, do not return a buffer - for a quoted string. If there is data, but the result of - next_char() would not fit in a char (for example, CHAR_EOF or - CHAR_QUOTE) or there is no readahead data available, return NULL, - and the caller must use next_char(). If there is no more data, - return buffer_retry. The buffer is only valid until the next - consume_buffer() or next_char(). */ - const char *(*buffer_func) (m4_input_block *, m4 *, size_t *, bool); - - /* Optional function to consume data from a readahead buffer - previously obtained through buffer_func. */ - void (*consume_func) (m4_input_block *, m4 *, size_t); -}; - -/* A block of input to be scanned. */ -struct m4_input_block -{ - m4_input_block *prev; /* Previous input_block on the input stack. */ - struct input_funcs *funcs; /* Virtual functions of this input_block. */ - const char *file; /* File where this input is from. */ - int line; /* Line where this input is from. */ - - union - { - struct - { - char *str; /* String value. */ - size_t len; /* Remaining length. */ - } - u_s; /* See string_funcs. */ - struct - { - FILE *fp; /* Input file handle. */ - bool_bitfield end : 1; /* True iff peek returned EOF. */ - bool_bitfield close : 1; /* True to close file on pop. */ - bool_bitfield line_start : 1; /* Saved start_of_input_line state. */ - } - u_f; /* See file_funcs. */ - struct - { - m4__symbol_chain *chain; /* Current link in chain. */ - m4__symbol_chain *end; /* Last link in chain. */ - } - u_c; /* See composite_funcs. */ - } - u; -}; - - -/* Obstack for storing individual tokens. */ -static m4_obstack token_stack; - -/* Obstack for storing input file names. */ -static m4_obstack file_names; - -/* Wrapup input stack. */ -static m4_obstack *wrapup_stack; - -/* Current stack, from input or wrapup. */ -static m4_obstack *current_input; - -/* Bottom of token_stack, for obstack_free. */ -static void *token_bottom; - -/* Pointer to top of current_input, never NULL. */ -static m4_input_block *isp; - -/* Pointer to top of wrapup_stack, never NULL. */ -static m4_input_block *wsp; - -/* Auxiliary for handling split m4_push_string (), NULL when not - pushing text for rescanning. */ -static m4_input_block *next; - -/* Flag for next_char () to increment current_line. */ -static bool start_of_input_line; - -/* Flag for next_char () to recognize change in input block. */ -static bool input_change; - -/* Vtable for handling input from files. */ -static struct input_funcs file_funcs = { - file_peek, file_read, file_unget, file_clean, file_print, file_buffer, - file_consume -}; - -/* Vtable for handling input from strings. */ -static struct input_funcs string_funcs = { - string_peek, string_read, string_unget, NULL, string_print, string_buffer, - string_consume -}; - -/* Vtable for handling input from composite chains. */ -static struct input_funcs composite_funcs = { - composite_peek, composite_read, composite_unget, composite_clean, - composite_print, composite_buffer, composite_consume -}; - -/* Vtable for recognizing end of input. */ -static struct input_funcs eof_funcs = { - eof_peek, eof_read, eof_unget, NULL, NULL, eof_buffer, NULL -}; - -/* Marker at end of an input stack. */ -static m4_input_block input_eof = { NULL, &eof_funcs, "", 0 }; - -/* Marker for buffer_func when current block has no more data. */ -static const char buffer_retry[1]; - - -/* Input files, from command line or [s]include. */ -static int -file_peek (m4_input_block *me, m4 *context M4_GNUC_UNUSED, - bool allow_argv M4_GNUC_UNUSED) -{ - int ch; - - ch = me->u.u_f.end ? EOF : getc (me->u.u_f.fp); - if (ch == EOF) - { - me->u.u_f.end = true; - return CHAR_RETRY; - } - - ungetc (ch, me->u.u_f.fp); - return ch; -} - -static int -file_read (m4_input_block *me, m4 *context, bool allow_quote M4_GNUC_UNUSED, - bool allow_argv M4_GNUC_UNUSED, bool allow_unget M4_GNUC_UNUSED) -{ - int ch; - - if (start_of_input_line) - { - start_of_input_line = false; - m4_set_current_line (context, ++me->line); - } - - /* If stdin is a terminal, calling getc after peek_char already - called it would make the user have to hit ^D twice to quit. */ - ch = me->u.u_f.end ? EOF : getc (me->u.u_f.fp); - if (ch == EOF) - { - me->u.u_f.end = true; - return CHAR_RETRY; - } - - if (ch == '\n') - start_of_input_line = true; - return ch; -} - -static void -file_unget (m4_input_block *me, int ch) -{ - assert (ch < CHAR_EOF); - if (ungetc (ch, me->u.u_f.fp) < 0) - { - assert (!"INTERNAL ERROR: failed ungetc!"); - abort (); /* ungetc should not be called without a previous read. */ - } - me->u.u_f.end = false; - if (ch == '\n') - start_of_input_line = false; -} - -static bool -file_clean (m4_input_block *me, m4 *context, bool cleanup) -{ - if (!cleanup) - return false; - if (me->prev != &input_eof) - m4_debug_message (context, M4_DEBUG_TRACE_INPUT, - _("input reverted to %s, line %d"), - me->prev->file, me->prev->line); - else - m4_debug_message (context, M4_DEBUG_TRACE_INPUT, _("input exhausted")); - - if (ferror (me->u.u_f.fp)) - { - m4_error (context, 0, 0, NULL, _("error reading %s"), - quotearg_style (locale_quoting_style, me->file)); - if (me->u.u_f.close) - fclose (me->u.u_f.fp); - } - else if (me->u.u_f.close && fclose (me->u.u_f.fp) == EOF) - m4_error (context, 0, errno, NULL, _("error reading %s"), - quotearg_style (locale_quoting_style, me->file)); - start_of_input_line = me->u.u_f.line_start; - m4_set_output_line (context, -1); - return true; -} - -static void -file_print (m4_input_block *me, m4 *context M4_GNUC_UNUSED, m4_obstack *obs, - int debug_level M4_GNUC_UNUSED) -{ - const char *text = me->file; - assert (obstack_object_size (current_input) == 0); - obstack_grow (obs, "'); -} - -static const char * -file_buffer (m4_input_block *me, m4 *context M4_GNUC_UNUSED, size_t *len, - bool allow_quote M4_GNUC_UNUSED) -{ - if (start_of_input_line) - { - start_of_input_line = false; - m4_set_current_line (context, ++me->line); - } - if (me->u.u_f.end) - return buffer_retry; - return freadptr (isp->u.u_f.fp, len); -} - -static void -file_consume (m4_input_block *me, m4 *context, size_t len) -{ - const char *buf; - const char *p; - size_t buf_len; - assert (!start_of_input_line); - buf = freadptr (me->u.u_f.fp, &buf_len); - assert (buf && len <= buf_len); - buf_len = 0; - while ((p = (char *) memchr (buf + buf_len, '\n', len - buf_len))) - { - if (p == buf + len - 1) - start_of_input_line = true; - else - m4_set_current_line (context, ++me->line); - buf_len = p - buf + 1; - } - if (freadseek (isp->u.u_f.fp, len) != 0) - assert (false); -} - -/* m4_push_file () pushes an input file FP with name TITLE on the - input stack, saving the current file name and line number. If next - is non-NULL, this push invalidates a call to m4_push_string_init (), - whose storage is consequently released. If CLOSE, then close FP at - end of file. - - file_read () manages line numbers for error messages, so they do not - get wrong due to lookahead. The token consisting of a newline - alone is taken as belonging to the line it ends, and the current - line number is not incremented until the next character is read. */ -void -m4_push_file (m4 *context, FILE *fp, const char *title, bool close_file) -{ - m4_input_block *i; - - if (next != NULL) - { - obstack_free (current_input, next); - next = NULL; - } - - m4_debug_message (context, M4_DEBUG_TRACE_INPUT, _("input read from %s"), - quotearg_style (locale_quoting_style, title)); - - i = (m4_input_block *) obstack_alloc (current_input, sizeof *i); - i->funcs = &file_funcs; - /* Save title on a separate obstack, so that wrapped text can refer - to it even after the file is popped. */ - i->file = obstack_copy0 (&file_names, title, strlen (title)); - i->line = 1; - - i->u.u_f.fp = fp; - i->u.u_f.end = false; - i->u.u_f.close = close_file; - i->u.u_f.line_start = start_of_input_line; - - m4_set_output_line (context, -1); - - i->prev = isp; - isp = i; - input_change = true; -} - - -/* Handle string expansion text. */ -static int -string_peek (m4_input_block *me, m4 *context M4_GNUC_UNUSED, - bool allow_argv M4_GNUC_UNUSED) -{ - return me->u.u_s.len ? to_uchar (*me->u.u_s.str) : CHAR_RETRY; -} - -static int -string_read (m4_input_block *me, m4 *context M4_GNUC_UNUSED, - bool allow_quote M4_GNUC_UNUSED, bool allow_argv M4_GNUC_UNUSED, - bool allow_unget M4_GNUC_UNUSED) -{ - if (!me->u.u_s.len) - return CHAR_RETRY; - me->u.u_s.len--; - return to_uchar (*me->u.u_s.str++); -} - -static void -string_unget (m4_input_block *me, int ch) -{ - assert (ch < CHAR_EOF && to_uchar (me->u.u_s.str[-1]) == ch); - me->u.u_s.str--; - me->u.u_s.len++; -} - -static void -string_print (m4_input_block *me, m4 *context, m4_obstack *obs, - int debug_level) -{ - bool quote = (debug_level & M4_DEBUG_TRACE_QUOTE) != 0; - size_t arg_length = m4_get_max_debug_arg_length_opt (context); - - assert (!me->u.u_s.len); - m4_shipout_string_trunc (obs, (char *) obstack_base (current_input), - obstack_object_size (current_input), - quote ? m4_get_syntax_quotes (M4SYNTAX) : NULL, - &arg_length); -} - -static const char * -string_buffer (m4_input_block *me, m4 *context M4_GNUC_UNUSED, size_t *len, - bool allow_quote M4_GNUC_UNUSED) -{ - if (!me->u.u_s.len) - return buffer_retry; - *len = me->u.u_s.len; - return me->u.u_s.str; -} - -static void -string_consume (m4_input_block *me, m4 *context M4_GNUC_UNUSED, size_t len) -{ - assert (len <= me->u.u_s.len); - me->u.u_s.len -= len; - me->u.u_s.str += len; -} - -/* First half of m4_push_string (). The pointer next points to the - new input_block. FILE and LINE describe the location where the - macro starts that is generating the expansion (even if the location - has advanced in the meantime). Return the obstack that will - collect the expansion text. */ -m4_obstack * -m4_push_string_init (m4 *context, const char *file, int line) -{ - /* Free any memory occupied by completely parsed input. */ - assert (!next); - while (pop_input (context, false)); - - /* Reserve the next location on the obstack. */ - next = (m4_input_block *) obstack_alloc (current_input, sizeof *next); - next->funcs = &string_funcs; - next->file = file; - next->line = line; - next->u.u_s.len = 0; - - return current_input; -} - -/* This function allows gathering input from multiple locations, - rather than copying everything consecutively onto the input stack. - Must be called between push_string_init and push_string_finish. - - Convert the current input block into a chain if it is not one - already, and add the contents of VALUE as a new link in the chain. - LEVEL describes the current expansion level, or SIZE_MAX if VALUE - is composite, its contents reside entirely on the current_input - stack, and VALUE lives in temporary storage. If VALUE is a simple - string, then it belongs to the current macro expansion. If VALUE - is composite, then each text link has a level of SIZE_MAX if it - belongs to the current macro expansion, otherwise it is a - back-reference where level tracks which stack it came from. The - resulting input block chain contains links with a level of SIZE_MAX - if the text belongs to the input stack, otherwise the level where - the back-reference comes from. - - Return true only if a reference was created to the contents of - VALUE, in which case, LEVEL is less than SIZE_MAX and the lifetime - of VALUE and its contents must last as long as the input engine can - parse references from it. INUSE determines whether composite - symbols should favor creating back-references or copying text. */ -bool -m4__push_symbol (m4 *context, m4_symbol_value *value, size_t level, bool inuse) -{ - m4__symbol_chain *src_chain = NULL; - m4__symbol_chain *chain; - - assert (next); - - /* Speed consideration - for short enough symbols, the speed and - memory overhead of parsing another INPUT_CHAIN link outweighs the - time to inline the symbol text. But don't copy text if it - already lives on the obstack. */ - if (m4_is_symbol_value_text (value)) - { - assert (level < SIZE_MAX); - if (m4_get_symbol_value_len (value) <= INPUT_INLINE_THRESHOLD) - { - obstack_grow (current_input, m4_get_symbol_value_text (value), - m4_get_symbol_value_len (value)); - return false; - } - } - else if (m4_is_symbol_value_func (value)) - { - if (next->funcs == &string_funcs) - { - next->funcs = &composite_funcs; - next->u.u_c.chain = next->u.u_c.end = NULL; - } - m4__append_builtin (current_input, value->u.builtin, &next->u.u_c.chain, - &next->u.u_c.end); - return false; - } - else - { - /* For composite values, if argv is already in use, creating - additional references for long text segments is more - efficient in time. But if argv is not yet in use, and we - have a composite value, then the value must already contain a - back-reference, and memory usage is more efficient if we can - avoid using the current expand_macro, even if it means larger - copies. */ - assert (value->type == M4_SYMBOL_COMP); - src_chain = value->u.u_c.chain; - while (level < SIZE_MAX && src_chain && src_chain->type == M4__CHAIN_STR - && (src_chain->u.u_s.len <= INPUT_INLINE_THRESHOLD - || (!inuse && src_chain->u.u_s.level == SIZE_MAX))) - { - obstack_grow (current_input, src_chain->u.u_s.str, - src_chain->u.u_s.len); - src_chain = src_chain->next; - } - if (!src_chain) - return false; - } - - if (next->funcs == &string_funcs) - { - next->funcs = &composite_funcs; - next->u.u_c.chain = next->u.u_c.end = NULL; - } - m4__make_text_link (current_input, &next->u.u_c.chain, &next->u.u_c.end); - if (m4_is_symbol_value_text (value)) - { - chain = (m4__symbol_chain *) obstack_alloc (current_input, - sizeof *chain); - if (next->u.u_c.end) - next->u.u_c.end->next = chain; - else - next->u.u_c.chain = chain; - next->u.u_c.end = chain; - chain->next = NULL; - chain->type = M4__CHAIN_STR; - chain->quote_age = m4_get_symbol_value_quote_age (value); - chain->u.u_s.str = m4_get_symbol_value_text (value); - chain->u.u_s.len = m4_get_symbol_value_len (value); - chain->u.u_s.level = level; - m4__adjust_refcount (context, level, true); - inuse = true; - } - while (src_chain) - { - if (src_chain->type == M4__CHAIN_FUNC) - { - m4__append_builtin (current_input, src_chain->u.builtin, - &next->u.u_c.chain, &next->u.u_c.end); - src_chain = src_chain->next; - continue; - } - if (level == SIZE_MAX) - { - /* Nothing to copy, since link already lives on obstack. */ - assert (src_chain->type != M4__CHAIN_STR - || src_chain->u.u_s.level == SIZE_MAX); - chain = src_chain; - } - else - { - /* Allow inlining the final link with subsequent text. */ - if (!src_chain->next && src_chain->type == M4__CHAIN_STR - && (src_chain->u.u_s.len <= INPUT_INLINE_THRESHOLD - || (!inuse && src_chain->u.u_s.level == SIZE_MAX))) - { - obstack_grow (current_input, src_chain->u.u_s.str, - src_chain->u.u_s.len); - break; - } - /* We must clone each link in the chain, since next_char - destructively modifies the chain it is parsing. */ - chain = (m4__symbol_chain *) obstack_copy (current_input, src_chain, - sizeof *chain); - chain->next = NULL; - if (chain->type == M4__CHAIN_STR && chain->u.u_s.level == SIZE_MAX) - { - if (chain->u.u_s.len <= INPUT_INLINE_THRESHOLD || !inuse) - chain->u.u_s.str = (char *) obstack_copy (current_input, - chain->u.u_s.str, - chain->u.u_s.len); - else - { - chain->u.u_s.level = level; - inuse = true; - } - } - } - if (next->u.u_c.end) - next->u.u_c.end->next = chain; - else - next->u.u_c.chain = chain; - next->u.u_c.end = chain; - if (chain->type == M4__CHAIN_ARGV) - { - assert (!chain->u.u_a.comma && !chain->u.u_a.skip_last); - inuse |= m4__arg_adjust_refcount (context, chain->u.u_a.argv, true); - } - else if (chain->type == M4__CHAIN_STR && chain->u.u_s.level < SIZE_MAX) - m4__adjust_refcount (context, chain->u.u_s.level, true); - src_chain = src_chain->next; - } - return inuse; -} - -/* Last half of m4_push_string (). If next is now NULL, a call to - m4_push_file () has pushed a different input block to the top of - the stack. Otherwise, all unfinished text on the obstack returned - from push_string_init is collected into the input stack. If the - new object is empty, we do not push it. */ -void -m4_push_string_finish (void) -{ - size_t len = obstack_object_size (current_input); - - if (next == NULL) - { - assert (!len); - return; - } - - if (len || next->funcs == &composite_funcs) - { - if (next->funcs == &string_funcs) - { - next->u.u_s.str = (char *) obstack_finish (current_input); - next->u.u_s.len = len; - } - else - m4__make_text_link (current_input, &next->u.u_c.chain, - &next->u.u_c.end); - next->prev = isp; - isp = next; - input_change = true; - } - else - obstack_free (current_input, next); - next = NULL; -} - - -/* A composite block contains multiple sub-blocks which are processed - in FIFO order, even though the obstack allocates memory in LIFO - order. */ -static int -composite_peek (m4_input_block *me, m4 *context, bool allow_argv) -{ - m4__symbol_chain *chain = me->u.u_c.chain; - size_t argc; - - while (chain) - { - switch (chain->type) - { - case M4__CHAIN_STR: - if (chain->u.u_s.len) - return to_uchar (chain->u.u_s.str[0]); - break; - case M4__CHAIN_FUNC: - if (chain->u.builtin) - return CHAR_BUILTIN; - break; - case M4__CHAIN_ARGV: - argc = m4_arg_argc (chain->u.u_a.argv); - if (chain->u.u_a.index == argc) - break; - if (chain->u.u_a.comma) - return ','; /* FIXME - support M4_SYNTAX_COMMA. */ - /* Only return a reference in the quoting is correct and the - reference has more than one argument left. */ - if (allow_argv && chain->quote_age == m4__quote_age (M4SYNTAX) - && chain->u.u_a.quotes && chain->u.u_a.index + 1 < argc) - return CHAR_ARGV; - /* Rather than directly parse argv here, we push another - input block containing the next unparsed argument from - argv. */ - m4_push_string_init (context, me->file, me->line); - m4__push_arg_quote (context, current_input, chain->u.u_a.argv, - chain->u.u_a.index, - m4__quote_cache (M4SYNTAX, NULL, - chain->quote_age, - chain->u.u_a.quotes)); - chain->u.u_a.index++; - chain->u.u_a.comma = true; - m4_push_string_finish (); - return peek_char (context, allow_argv); - case M4__CHAIN_LOC: - break; - default: - assert (!"composite_peek"); - abort (); - } - chain = chain->next; - } - return CHAR_RETRY; -} - -static int -composite_read (m4_input_block *me, m4 *context, bool allow_quote, - bool allow_argv, bool allow_unget) -{ - m4__symbol_chain *chain = me->u.u_c.chain; - size_t argc; - while (chain) - { - if (allow_quote && chain->quote_age == m4__quote_age (M4SYNTAX)) - return CHAR_QUOTE; - switch (chain->type) - { - case M4__CHAIN_STR: - if (chain->u.u_s.len) - { - /* Partial consumption invalidates quote age. */ - chain->quote_age = 0; - chain->u.u_s.len--; - return to_uchar (*chain->u.u_s.str++); - } - if (chain->u.u_s.level < SIZE_MAX) - m4__adjust_refcount (context, chain->u.u_s.level, false); - break; - case M4__CHAIN_FUNC: - if (chain->u.builtin) - return CHAR_BUILTIN; - break; - case M4__CHAIN_ARGV: - argc = m4_arg_argc (chain->u.u_a.argv); - if (chain->u.u_a.index == argc) - { - m4__arg_adjust_refcount (context, chain->u.u_a.argv, false); - break; - } - if (chain->u.u_a.comma) - { - chain->u.u_a.comma = false; - return ','; /* FIXME - support M4_SYNTAX_COMMA. */ - } - /* Only return a reference in the quoting is correct and the - reference has more than one argument left. */ - if (allow_argv && chain->quote_age == m4__quote_age (M4SYNTAX) - && chain->u.u_a.quotes && chain->u.u_a.index + 1 < argc) - return CHAR_ARGV; - /* Rather than directly parse argv here, we push another - input block containing the next unparsed argument from - argv. */ - m4_push_string_init (context, me->file, me->line); - m4__push_arg_quote (context, current_input, chain->u.u_a.argv, - chain->u.u_a.index, - m4__quote_cache (M4SYNTAX, NULL, - chain->quote_age, - chain->u.u_a.quotes)); - chain->u.u_a.index++; - chain->u.u_a.comma = true; - m4_push_string_finish (); - return next_char (context, allow_quote, allow_argv, allow_unget); - case M4__CHAIN_LOC: - me->file = chain->u.u_l.file; - me->line = chain->u.u_l.line; - input_change = true; - me->u.u_c.chain = chain->next; - return next_char (context, allow_quote, allow_argv, allow_unget); - default: - assert (!"composite_read"); - abort (); - } - me->u.u_c.chain = chain = chain->next; - } - return CHAR_RETRY; -} - -static void -composite_unget (m4_input_block *me, int ch) -{ - m4__symbol_chain *chain = me->u.u_c.chain; - switch (chain->type) - { - case M4__CHAIN_STR: - assert (ch < CHAR_EOF && to_uchar (chain->u.u_s.str[-1]) == ch); - chain->u.u_s.str--; - chain->u.u_s.len++; - break; - case M4__CHAIN_FUNC: - assert (ch == CHAR_BUILTIN && chain->u.builtin); - break; - case M4__CHAIN_ARGV: - /* FIXME - support M4_SYNTAX_COMMA. */ - assert (ch == ',' && !chain->u.u_a.comma); - chain->u.u_a.comma = true; - break; - default: - assert (!"composite_unget"); - abort (); - } -} - -static bool -composite_clean (m4_input_block *me, m4 *context, bool cleanup) -{ - m4__symbol_chain *chain = me->u.u_c.chain; - assert (!chain || !cleanup); - while (chain) - { - switch (chain->type) - { - case M4__CHAIN_STR: - if (chain->u.u_s.len) - { - assert (!cleanup); - return false; - } - if (chain->u.u_s.level < SIZE_MAX) - m4__adjust_refcount (context, chain->u.u_s.level, false); - break; - case M4__CHAIN_FUNC: - if (chain->u.builtin) - return false; - break; - case M4__CHAIN_ARGV: - if (chain->u.u_a.index < m4_arg_argc (chain->u.u_a.argv)) - { - assert (!cleanup); - return false; - } - m4__arg_adjust_refcount (context, chain->u.u_a.argv, false); - break; - case M4__CHAIN_LOC: - return false; - default: - assert (!"composite_clean"); - abort (); - } - me->u.u_c.chain = chain = chain->next; - } - return true; -} - -static void -composite_print (m4_input_block *me, m4 *context, m4_obstack *obs, - int debug_level) -{ - bool quote = (debug_level & M4_DEBUG_TRACE_QUOTE) != 0; - size_t maxlen = m4_get_max_debug_arg_length_opt (context); - m4__symbol_chain *chain = me->u.u_c.chain; - const m4_string_pair *quotes = m4_get_syntax_quotes (M4SYNTAX); - bool module = (debug_level & M4_DEBUG_TRACE_MODULE) != 0; - bool done = false; - size_t len = obstack_object_size (current_input); - - if (quote) - m4_shipout_string (context, obs, quotes->str1, quotes->len1, false); - while (chain && !done) - { - switch (chain->type) - { - case M4__CHAIN_STR: - if (m4_shipout_string_trunc (obs, chain->u.u_s.str, - chain->u.u_s.len, NULL, &maxlen)) - done = true; - break; - case M4__CHAIN_FUNC: - m4__builtin_print (obs, chain->u.builtin, false, NULL, NULL, module); - break; - case M4__CHAIN_ARGV: - assert (!chain->u.u_a.comma); - if (m4__arg_print (context, obs, chain->u.u_a.argv, - chain->u.u_a.index, - m4__quote_cache (M4SYNTAX, NULL, chain->quote_age, - chain->u.u_a.quotes), - chain->u.u_a.flatten, NULL, NULL, &maxlen, false, - module)) - done = true; - break; - default: - assert (!"composite_print"); - abort (); - } - chain = chain->next; - } - if (len) - m4_shipout_string_trunc (obs, (char *) obstack_base (current_input), len, - NULL, &maxlen); - if (quote) - m4_shipout_string (context, obs, quotes->str2, quotes->len2, false); -} - -static const char * -composite_buffer (m4_input_block *me, m4 *context, size_t *len, - bool allow_quote) -{ - m4__symbol_chain *chain = me->u.u_c.chain; - while (chain) - { - if (allow_quote && chain->quote_age == m4__quote_age (M4SYNTAX)) - return NULL; /* CHAR_QUOTE doesn't fit in buffer. */ - switch (chain->type) - { - case M4__CHAIN_STR: - if (chain->u.u_s.len) - { - *len = chain->u.u_s.len; - return chain->u.u_s.str; - } - if (chain->u.u_s.level < SIZE_MAX) - m4__adjust_refcount (context, chain->u.u_s.level, false); - break; - case M4__CHAIN_FUNC: - if (chain->u.builtin) - return NULL; /* CHAR_BUILTIN doesn't fit in buffer. */ - break; - case M4__CHAIN_ARGV: - if (chain->u.u_a.index == m4_arg_argc (chain->u.u_a.argv)) - { - m4__arg_adjust_refcount (context, chain->u.u_a.argv, false); - break; - } - return NULL; /* No buffer to provide. */ - case M4__CHAIN_LOC: - me->file = chain->u.u_l.file; - me->line = chain->u.u_l.line; - input_change = true; - me->u.u_c.chain = chain->next; - return next_buffer (context, len, allow_quote); - default: - assert (!"composite_buffer"); - abort (); - } - me->u.u_c.chain = chain = chain->next; - } - return buffer_retry; -} - -static void -composite_consume (m4_input_block *me, m4 *context M4_GNUC_UNUSED, size_t len) -{ - m4__symbol_chain *chain = me->u.u_c.chain; - assert (chain && chain->type == M4__CHAIN_STR && len <= chain->u.u_s.len); - /* Partial consumption invalidates quote age. */ - chain->quote_age = 0; - chain->u.u_s.len -= len; - chain->u.u_s.str += len; -} - -/* Given an obstack OBS, capture any unfinished text as a link in the - chain that starts at *START and ends at *END. START may be NULL if - *END is non-NULL. */ -void -m4__make_text_link (m4_obstack *obs, m4__symbol_chain **start, - m4__symbol_chain **end) -{ - m4__symbol_chain *chain; - size_t len = obstack_object_size (obs); - - assert (end && (start || *end)); - if (len) - { - char *str = (char *) obstack_finish (obs); - chain = (m4__symbol_chain *) obstack_alloc (obs, sizeof *chain); - if (*end) - (*end)->next = chain; - else - *start = chain; - *end = chain; - chain->next = NULL; - chain->type = M4__CHAIN_STR; - chain->quote_age = 0; - chain->u.u_s.str = str; - chain->u.u_s.len = len; - chain->u.u_s.level = SIZE_MAX; - } -} - -/* Given an obstack OBS, capture any unfinished text as a link, then - append the builtin FUNC as the next link in the chain that starts - at *START and ends at *END. START may be NULL if *END is - non-NULL. */ -void -m4__append_builtin (m4_obstack *obs, const m4__builtin *func, - m4__symbol_chain **start, m4__symbol_chain **end) -{ - m4__symbol_chain *chain; - - assert (func); - m4__make_text_link (obs, start, end); - chain = (m4__symbol_chain *) obstack_alloc (obs, sizeof *chain); - if (*end) - (*end)->next = chain; - else - *start = chain; - *end = chain; - chain->next = NULL; - chain->type = M4__CHAIN_FUNC; - chain->quote_age = 0; - chain->u.builtin = func; -} - -/* Push TOKEN, which contains a builtin's definition, onto the obstack - OBS, which is either input stack or the wrapup stack. */ -void -m4_push_builtin (m4 *context, m4_obstack *obs, m4_symbol_value *token) -{ - m4_input_block *i = (obs == current_input ? next : wsp); - assert (i); - if (i->funcs == &string_funcs) - { - i->funcs = &composite_funcs; - i->u.u_c.chain = i->u.u_c.end = NULL; - } - else - assert (i->funcs == &composite_funcs); - m4__append_builtin (obs, token->u.builtin, &i->u.u_c.chain, &i->u.u_c.end); -} - - -/* End of input optimization. By providing these dummy callback - functions, we guarantee that the input stack is never NULL, and - thus make fewer execution branches. */ -static int -eof_peek (m4_input_block *me, m4 *context M4_GNUC_UNUSED, - bool allow_argv M4_GNUC_UNUSED) -{ - assert (me == &input_eof); - return CHAR_EOF; -} - -static int -eof_read (m4_input_block *me, m4 *context M4_GNUC_UNUSED, - bool allow_quote M4_GNUC_UNUSED, bool allow_argv M4_GNUC_UNUSED, - bool allow_unget M4_GNUC_UNUSED) -{ - assert (me == &input_eof); - return CHAR_EOF; -} - -static void -eof_unget (m4_input_block *me M4_GNUC_UNUSED, int ch) -{ - assert (ch == CHAR_EOF); -} - -static const char * -eof_buffer (m4_input_block *me M4_GNUC_UNUSED, m4 *context M4_GNUC_UNUSED, - size_t *len M4_GNUC_UNUSED, bool allow_unget M4_GNUC_UNUSED) -{ - return NULL; -} - - -/* When tracing, print a summary of the contents of the input block - created by push_string_init/push_string_finish to OBS. Use - DEBUG_LEVEL to determine whether to add quotes or module - designations. */ -void -m4_input_print (m4 *context, m4_obstack *obs, int debug_level) -{ - m4_input_block *block = next ? next : isp; - assert (context && obs && (debug_level & M4_DEBUG_TRACE_EXPANSION)); - assert (block->funcs->print_func); - block->funcs->print_func (block, context, obs, debug_level); -} - -/* Return an obstack ready for direct expansion of wrapup text, and - set *END to the location that should be updated if any builtin - tokens are wrapped. Store the location of CALLER with the wrapped - text. This should be followed by m4__push_wrapup_finish (). */ -m4_obstack * -m4__push_wrapup_init (m4 *context, const m4_call_info *caller, - m4__symbol_chain ***end) -{ - m4_input_block *i; - m4__symbol_chain *chain; - - assert (obstack_object_size (wrapup_stack) == 0); - if (wsp != &input_eof) - { - i = wsp; - assert (i->funcs == &composite_funcs && i->u.u_c.end - && i->u.u_c.end->type != M4__CHAIN_LOC); - } - else - { - i = (m4_input_block *) obstack_alloc (wrapup_stack, sizeof *i); - i->prev = wsp; - i->funcs = &composite_funcs; - i->file = caller->file; - i->line = caller->line; - i->u.u_c.chain = i->u.u_c.end = NULL; - wsp = i; - } - chain = (m4__symbol_chain *) obstack_alloc (wrapup_stack, sizeof *chain); - if (i->u.u_c.end) - i->u.u_c.end->next = chain; - else - i->u.u_c.chain = chain; - i->u.u_c.end = chain; - chain->next = NULL; - chain->type = M4__CHAIN_LOC; - chain->quote_age = 0; - chain->u.u_l.file = caller->file; - chain->u.u_l.line = caller->line; - *end = &i->u.u_c.end; - return wrapup_stack; -} - -/* After pushing wrapup text, this completes the bookkeeping. */ -void -m4__push_wrapup_finish (void) -{ - m4__make_text_link (wrapup_stack, &wsp->u.u_c.chain, &wsp->u.u_c.end); - assert (wsp->u.u_c.end->type != M4__CHAIN_LOC); -} - - -/* The function pop_input () pops one level of input sources. If - CLEANUP, the current_file and current_line are restored as needed. - The return value is false if cleanup is still required, or if the - current input source is not at the end. */ -static bool -pop_input (m4 *context, bool cleanup) -{ - m4_input_block *tmp = isp->prev; - - assert (isp); - if (isp->funcs->clean_func - ? !isp->funcs->clean_func (isp, context, cleanup) - : (isp->funcs->peek_func (isp, context, true) != CHAR_RETRY)) - return false; - - obstack_free (current_input, isp); - m4__quote_uncache (M4SYNTAX); - next = NULL; /* might be set in m4_push_string_init () */ - - isp = tmp; - input_change = true; - return true; -} - -/* To switch input over to the wrapup stack, main calls pop_wrapup. - Since wrapup text can install new wrapup text, pop_wrapup () - returns true if there is more wrapped text to parse. */ -bool -m4_pop_wrapup (m4 *context) -{ - static size_t level = 0; - - next = NULL; - obstack_free (current_input, NULL); - free (current_input); - - if (wsp == &input_eof) - { - obstack_free (wrapup_stack, NULL); - m4_set_current_file (context, NULL); - m4_set_current_line (context, 0); - m4_debug_message (context, M4_DEBUG_TRACE_INPUT, - _("input from m4wrap exhausted")); - current_input = NULL; - DELETE (wrapup_stack); - return false; - } - - m4_debug_message (context, M4_DEBUG_TRACE_INPUT, - _("input from m4wrap recursion level %zu"), ++level); - - current_input = wrapup_stack; - wrapup_stack = (m4_obstack *) xmalloc (sizeof *wrapup_stack); - obstack_init (wrapup_stack); - - isp = wsp; - wsp = &input_eof; - input_change = true; - - return true; -} - -/* Populate TOKEN with the builtin token at the top of the input - stack, then consume the input. If OBS, TOKEN will be converted to - a composite token using storage from OBS as necessary; otherwise, - if TOKEN is NULL, the builtin token is discarded. */ -static void -init_builtin_token (m4 *context, m4_obstack *obs, m4_symbol_value *token) -{ - m4__symbol_chain *chain; - assert (isp->funcs == &composite_funcs); - chain = isp->u.u_c.chain; - assert (!chain->quote_age && chain->type == M4__CHAIN_FUNC - && chain->u.builtin); - if (obs) - { - assert (token); - if (token->type == M4_SYMBOL_VOID) - { - token->type = M4_SYMBOL_COMP; - token->u.u_c.chain = token->u.u_c.end = NULL; - token->u.u_c.wrapper = false; - token->u.u_c.has_func = false; - } - assert (token->type == M4_SYMBOL_COMP); - m4__append_builtin (obs, chain->u.builtin, &token->u.u_c.chain, - &token->u.u_c.end); - } - else if (token) - { - assert (token->type == M4_SYMBOL_VOID); - m4__set_symbol_value_builtin (token, chain->u.builtin); - } - chain->u.builtin = NULL; -} - -/* When a QUOTE token is seen, convert VALUE to a composite (if it is - not one already), consisting of any unfinished text on OBS, as well - as the quoted token from the top of the input stack. Use OBS for - any additional allocations needed to store the token chain. */ -static void -append_quote_token (m4 *context, m4_obstack *obs, m4_symbol_value *value) -{ - m4__symbol_chain *src_chain = isp->u.u_c.chain; - m4__symbol_chain *chain; - assert (isp->funcs == &composite_funcs && obs && m4__quote_age (M4SYNTAX)); - isp->u.u_c.chain = src_chain->next; - - /* Speed consideration - for short enough symbols, the speed and - memory overhead of parsing another INPUT_CHAIN link outweighs the - time to inline the symbol text. */ - if (src_chain->type == M4__CHAIN_STR - && src_chain->u.u_s.len <= INPUT_INLINE_THRESHOLD) - { - assert (src_chain->u.u_s.level <= SIZE_MAX); - obstack_grow (obs, src_chain->u.u_s.str, src_chain->u.u_s.len); - m4__adjust_refcount (context, src_chain->u.u_s.level, false); - return; - } - - if (value->type == M4_SYMBOL_VOID) - { - value->type = M4_SYMBOL_COMP; - value->u.u_c.chain = value->u.u_c.end = NULL; - value->u.u_c.wrapper = value->u.u_c.has_func = false; - } - assert (value->type == M4_SYMBOL_COMP); - m4__make_text_link (obs, &value->u.u_c.chain, &value->u.u_c.end); - chain = (m4__symbol_chain *) obstack_copy (obs, src_chain, sizeof *chain); - if (value->u.u_c.end) - value->u.u_c.end->next = chain; - else - value->u.u_c.chain = chain; - value->u.u_c.end = chain; - if (chain->type == M4__CHAIN_ARGV && chain->u.u_a.has_func) - value->u.u_c.has_func = true; - chain->next = NULL; -} - -/* When an ARGV token is seen, convert VALUE to point to it via a - composite chain. Use OBS for any additional allocations - needed. */ -static void -init_argv_symbol (m4 *context, m4_obstack *obs, m4_symbol_value *value) -{ - m4__symbol_chain *src_chain; - m4__symbol_chain *chain; - int ch; - const m4_string_pair *comments = m4_get_syntax_comments (M4SYNTAX); - - assert (value->type == M4_SYMBOL_VOID && isp->funcs == &composite_funcs - && isp->u.u_c.chain->type == M4__CHAIN_ARGV - && obs && obstack_object_size (obs) == 0); - - src_chain = isp->u.u_c.chain; - isp->u.u_c.chain = src_chain->next; - value->type = M4_SYMBOL_COMP; - /* Clone the link, since the input will be discarded soon. */ - chain = (m4__symbol_chain *) obstack_copy (obs, src_chain, sizeof *chain); - value->u.u_c.chain = value->u.u_c.end = chain; - value->u.u_c.wrapper = true; - value->u.u_c.has_func = chain->u.u_a.has_func; - chain->next = NULL; - - /* If the next character is not ',' or ')', then unlink the last - argument from argv and schedule it for reparsing. This way, - expand_argument never has to deal with concatenation of argv with - arbitrary text. Note that the implementation of safe_quotes - ensures peek_input won't return CHAR_ARGV if the user is perverse - enough to mix comment delimiters with argument separators: - - define(n,`$#')define(echo,$*)changecom(`,,',`)')n(echo(a,`,b`)'',c)) - => 2 (not 3) - - Therefore, we do not have to worry about calling MATCH, and thus - do not have to worry about pop_input being called and - invalidating the argv reference. - - When the $@ ref is used unchanged, we completely bypass the - decrement of the argv refcount in next_char, since the ref is - still live via the current collect_arguments. However, when the - last element of the $@ ref is reparsed, we must increase the argv - refcount here, to compensate for the fact that it will be - decreased once the final element is parsed. */ - assert (!comments->len1 - || (!m4_has_syntax (M4SYNTAX, *comments->str1, - M4_SYNTAX_COMMA | M4_SYNTAX_CLOSE) - && *comments->str1 != *src_chain->u.u_a.quotes->str1)); - ch = peek_char (context, true); - if (!m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_COMMA | M4_SYNTAX_CLOSE)) - { - isp->u.u_c.chain = src_chain; - src_chain->u.u_a.index = m4_arg_argc (chain->u.u_a.argv) - 1; - src_chain->u.u_a.comma = true; - chain->u.u_a.skip_last = true; - m4__arg_adjust_refcount (context, chain->u.u_a.argv, true); - } -} - - -/* Low level input is done a character at a time. The function - next_char () is used to read and advance the input to the next - character. If ALLOW_QUOTE, and the current input matches the - current quote age, return CHAR_QUOTE and leave consumption of data - for append_quote_token; otherwise, if ALLOW_ARGV, and the current - input matches an argv reference with the correct quoting, return - CHAR_ARGV and leave consumption of data for init_argv_symbol. If - ALLOW_UNGET, then pop input to avoid returning CHAR_RETRY, and - ensure that unget_input can safely be called next. */ -static int -next_char (m4 *context, bool allow_quote, bool allow_argv, bool allow_unget) -{ - int ch; - - while (1) - { - if (input_change) - { - m4_set_current_file (context, isp->file); - m4_set_current_line (context, isp->line); - input_change = false; - } - - assert (isp->funcs->read_func); - while (((ch = isp->funcs->read_func (isp, context, allow_quote, - allow_argv, allow_unget)) - != CHAR_RETRY) - || allow_unget) - { - /* if (!IS_IGNORE (ch)) */ - return ch; - } - - /* End of input source --- pop one level. */ - pop_input (context, true); - } -} - -/* The function peek_char () is used to look at the next character in - the input stream. At any given time, it reads from the input_block - on the top of the current input stack. If ALLOW_ARGV, then return - CHAR_ARGV if an entire $@ reference is available for use. */ -static int -peek_char (m4 *context, bool allow_argv) -{ - int ch; - m4_input_block *block = isp; - - while (1) - { - assert (block->funcs->peek_func); - ch = block->funcs->peek_func (block, context, allow_argv); - if (ch != CHAR_RETRY) - { -/* if (IS_IGNORE (ch)) */ -/* return next_char (context, false, true, false); */ - return ch; - } - - block = block->prev; - } -} - -/* The function unget_input () puts back a character on the input - stack, using an existing input_block if possible. This is not safe - to call except immediately after next_char(context, aq, aa, true). */ -static void -unget_input (int ch) -{ - assert (isp->funcs->unget_func != NULL); - isp->funcs->unget_func (isp, ch); -} - -/* Return a pointer to the available bytes of the current input block, - and set *LEN to the length of the result. If ALLOW_QUOTE, do not - return a buffer for a quoted string. If the result does not fit in - a char (for example, CHAR_EOF or CHAR_QUOTE), or if there is no - readahead data available, return NULL, and the caller must fall - back to next_char(). The buffer is only valid until the next - consume_buffer() or next_char(). */ -static const char * -next_buffer (m4 *context, size_t *len, bool allow_quote) -{ - const char *buf; - while (1) - { - assert (isp); - if (input_change) - { - m4_set_current_file (context, isp->file); - m4_set_current_line (context, isp->line); - input_change = false; - } - - assert (isp->funcs->buffer_func); - buf = isp->funcs->buffer_func (isp, context, len, allow_quote); - if (buf != buffer_retry) - return buf; - /* End of input source --- pop one level. */ - pop_input (context, true); - } -} - -/* Consume LEN bytes from the current input block, as though by LEN - calls to next_char(). LEN must be less than or equal to the - previous length returned by a successful call to next_buffer(). */ -static void -consume_buffer (m4 *context, size_t len) -{ - assert (isp && !input_change); - if (len) - { - assert (isp->funcs->consume_func); - isp->funcs->consume_func (isp, context, len); - } -} - -/* skip_line () simply discards all immediately following characters, - up to the first newline. It is only used from m4_dnl (). Report - errors on behalf of CALLER. */ -void -m4_skip_line (m4 *context, const m4_call_info *caller) -{ - int ch; - - while (1) - { - size_t len; - const char *buffer = next_buffer (context, &len, false); - if (buffer) - { - const char *p = (char *) memchr (buffer, '\n', len); - if (p) - { - consume_buffer (context, p - buffer + 1); - ch = '\n'; - break; - } - consume_buffer (context, len); - } - else - { - ch = next_char (context, false, false, false); - if (ch == CHAR_EOF || ch == '\n') - break; - } - } - if (ch == CHAR_EOF) - m4_warn (context, 0, caller, _("end of file treated as newline")); -} - - -/* If the string S of length LEN matches the next characters of the - input stream, return true. If CONSUME, the first byte has already - been matched. If a match is found and CONSUME is true, the input - is discarded; otherwise any characters read are pushed back again. - The function is used only when multicharacter quotes or comment - delimiters are used. - - All strings herein should be unsigned. Otherwise sign-extension - of individual chars might break quotes with 8-bit chars in it. - - FIXME - when matching multiquotes that cross file boundaries, we do - not properly restore the current input file and line when we - restore unconsumed characters. */ -static bool -match_input (m4 *context, const char *s, size_t len, bool consume) -{ - int n; /* number of characters matched */ - int ch; /* input character */ - const char *t; - m4_obstack *st; - bool result = false; - size_t buf_len; - - if (consume) - { - s++; - len--; - } - /* Try a buffer match first. */ - assert (len); - t = next_buffer (context, &buf_len, false); - if (t && len <= buf_len && memcmp (s, t, len) == 0) - { - if (consume) - consume_buffer (context, len); - return true; - } - /* Fall back on byte matching. */ - ch = peek_char (context, false); - if (ch != to_uchar (*s)) - return false; - - if (len == 1) - { - if (consume) - next_char (context, false, false, false); - return true; /* short match */ - } - - next_char (context, false, false, false); - for (n = 1, t = s++; peek_char (context, false) == to_uchar (*s++); ) - { - next_char (context, false, false, false); - n++; - if (--len == 1) /* long match */ - { - if (consume) - return true; - result = true; - break; - } - } - - /* Failed or shouldn't consume, push back input. */ - st = m4_push_string_init (context, m4_get_current_file (context), - m4_get_current_line (context)); - obstack_grow (st, t, n); - m4_push_string_finish (); - return result; -} - -/* Check whether the current input matches a delimiter, which either - belongs to syntax category CAT or matches the string S of length - LEN. The first character is handled inline for speed, and S[LEN] - must be safe to dereference (it is faster to do character - comparison prior to length checks). This improves efficiency for - the common case of single character quotes and comment delimiters, - while being safe for disabled delimiters as well as longer - delimiters. If CONSUME, then CH is the result of next_char, and a - successful match will discard the matched string. Otherwise, CH is - the result of peek_char, and the input stream is effectively - unchanged. */ -#define MATCH(C, ch, cat, s, len, consume) \ - (m4_has_syntax (m4_get_syntax_table (C), ch, cat) \ - || (to_uchar ((s)[0]) == (ch) \ - && ((len) >> 1 ? match_input (C, s, len, consume) : (len)))) - -/* While the current input character has the given SYNTAX, append it - to OBS. Take care not to pop input source unless the next source - would continue the chain. Return true if the chain ended with - CHAR_EOF. */ -static bool -consume_syntax (m4 *context, m4_obstack *obs, unsigned int syntax) -{ - int ch; - bool allow = m4__safe_quotes (M4SYNTAX); - assert (syntax); - while (1) - { - /* Start with a buffer search. */ - size_t len; - const char *buffer = next_buffer (context, &len, allow); - if (buffer) - { - const char *p = buffer; - while (len && m4_has_syntax (M4SYNTAX, *p, syntax)) - { - len--; - p++; - } - obstack_grow (obs, buffer, p - buffer); - consume_buffer (context, p - buffer); - if (len) - return false; - } - /* Fall back to byte-wise search. It is safe to call next_char - without first checking peek_char, except at input source - boundaries, which we detect by CHAR_RETRY. */ - ch = next_char (context, allow, allow, true); - if (ch < CHAR_EOF && m4_has_syntax (M4SYNTAX, ch, syntax)) - { - obstack_1grow (obs, ch); - continue; - } - if (ch == CHAR_RETRY || ch == CHAR_QUOTE || ch == CHAR_ARGV) - { - ch = peek_char (context, false); - /* We exploit the fact that CHAR_EOF, CHAR_BUILTIN, - CHAR_QUOTE, and CHAR_ARGV do not satisfy any syntax - categories. */ - if (m4_has_syntax (M4SYNTAX, ch, syntax)) - { - assert (ch < CHAR_EOF); - obstack_1grow (obs, ch); - next_char (context, false, false, false); - continue; - } - return ch == CHAR_EOF; - } - unget_input (ch); - return false; - } -} - - -/* Initialize input stacks. */ -void -m4_input_init (m4 *context) -{ - obstack_init (&file_names); - m4_set_current_file (context, NULL); - m4_set_current_line (context, 0); - - current_input = (m4_obstack *) xmalloc (sizeof *current_input); - obstack_init (current_input); - wrapup_stack = (m4_obstack *) xmalloc (sizeof *wrapup_stack); - obstack_init (wrapup_stack); - - /* Allocate an object in the current chunk, so that obstack_free - will always work even if the first token parsed spills to a new - chunk. */ - obstack_init (&token_stack); - token_bottom = obstack_finish (&token_stack); - - isp = &input_eof; - wsp = &input_eof; - next = NULL; - - start_of_input_line = false; -} - -/* Free memory used by the input engine. */ -void -m4_input_exit (void) -{ - assert (!current_input && isp == &input_eof); - assert (!wrapup_stack && wsp == &input_eof); - obstack_free (&file_names, NULL); - obstack_free (&token_stack, NULL); -} - - -/* Parse and return a single token from the input stream, constructed - into TOKEN. See m4__token_type for the valid return types, along - with a description of what TOKEN will contain. If LINE is not - NULL, set *LINE to the line number where the token starts. If OBS, - expand safe tokens (strings and comments) directly into OBS rather - than in a temporary staging area. If ALLOW_ARGV, OBS must be - non-NULL, and an entire series of arguments can be returned if a $@ - reference is encountered. Report errors (unterminated comments or - strings) on behalf of CALLER, if non-NULL. - - If OBS is NULL or the token expansion is unknown, the token text is - collected on the obstack token_stack, which never contains more - than one token text at a time. The storage pointed to by the - fields in TOKEN is therefore subject to change the next time - m4__next_token () is called. */ -m4__token_type -m4__next_token (m4 *context, m4_symbol_value *token, int *line, - m4_obstack *obs, bool allow_argv, const m4_call_info *caller) -{ - int ch; - int quote_level; - m4__token_type type; - const char *file = NULL; - size_t len; - /* The obstack where token data is stored. Generally token_stack, - for tokens where argument collection might not use the literal - token. But for comments and strings, we can output directly into - the argument collection obstack OBS, if provided. */ - m4_obstack *obs_safe = &token_stack; - - assert (next == NULL); - memset (token, '\0', sizeof *token); - do { - obstack_free (&token_stack, token_bottom); - - /* Must consume an input character. */ - ch = next_char (context, false, allow_argv && m4__quote_age (M4SYNTAX), - false); - if (line) - { - *line = m4_get_current_line (context); - file = m4_get_current_file (context); - } - if (ch == CHAR_EOF) /* EOF */ - { -#ifdef DEBUG_INPUT - xfprintf (stderr, "next_token -> EOF\n"); -#endif - return M4_TOKEN_EOF; - } - - if (ch == CHAR_BUILTIN) /* BUILTIN TOKEN */ - { - init_builtin_token (context, obs, token); -#ifdef DEBUG_INPUT - m4_print_token (context, "next_token", M4_TOKEN_MACDEF, token); -#endif - return M4_TOKEN_MACDEF; - } - if (ch == CHAR_ARGV) - { - init_argv_symbol (context, obs, token); -#ifdef DEBUG_INPUT - m4_print_token (context, "next_token", M4_TOKEN_ARGV, token); -#endif - return M4_TOKEN_ARGV; - } - - if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_ESCAPE)) - { /* ESCAPED WORD */ - obstack_1grow (&token_stack, ch); - if ((ch = next_char (context, false, false, false)) < CHAR_EOF) - { - obstack_1grow (&token_stack, ch); - if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_ALPHA)) - consume_syntax (context, &token_stack, - M4_SYNTAX_ALPHA | M4_SYNTAX_NUM); - type = M4_TOKEN_WORD; - } - else - type = M4_TOKEN_SIMPLE; /* escape before eof */ - } - else if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_ALPHA)) - { - type = (m4_is_syntax_macro_escaped (M4SYNTAX) - ? M4_TOKEN_STRING : M4_TOKEN_WORD); - if (type == M4_TOKEN_STRING && obs) - obs_safe = obs; - obstack_1grow (obs_safe, ch); - consume_syntax (context, obs_safe, M4_SYNTAX_ALPHA | M4_SYNTAX_NUM); - } - else if (MATCH (context, ch, M4_SYNTAX_LQUOTE, - context->syntax->quote.str1, - context->syntax->quote.len1, true)) - { /* QUOTED STRING */ - if (obs) - obs_safe = obs; - quote_level = 1; - type = M4_TOKEN_STRING; - while (1) - { - /* Start with buffer search for either potential delimiter. */ - size_t len; - const char *buffer = next_buffer (context, &len, - obs && m4__quote_age (M4SYNTAX)); - if (buffer) - { - const char *p = buffer; - if (m4_is_syntax_single_quotes (M4SYNTAX)) - do - { - p = (char *) memchr2 (p, *context->syntax->quote.str1, - *context->syntax->quote.str2, - buffer + len - p); - } - while (p && m4__quote_age (M4SYNTAX) - && (*p++ == *context->syntax->quote.str2 - ? --quote_level : ++quote_level)); - else - { - size_t remaining = len; - assert (context->syntax->quote.len1 == 1 - && context->syntax->quote.len2 == 1); - while (remaining && !m4_has_syntax (M4SYNTAX, *p, - (M4_SYNTAX_LQUOTE - | M4_SYNTAX_RQUOTE))) - { - p++; - remaining--; - } - if (!remaining) - p = NULL; - } - if (p) - { - if (m4__quote_age (M4SYNTAX)) - { - assert (!quote_level - && context->syntax->quote.len1 == 1 - && context->syntax->quote.len2 == 1); - obstack_grow (obs_safe, buffer, p - buffer - 1); - consume_buffer (context, p - buffer); - break; - } - obstack_grow (obs_safe, buffer, p - buffer); - ch = to_uchar (*p); - consume_buffer (context, p - buffer + 1); - } - else - { - obstack_grow (obs_safe, buffer, len); - consume_buffer (context, len); - continue; - } - } - /* Fall back to byte-wise search. */ - else - ch = next_char (context, obs && m4__quote_age (M4SYNTAX), false, - false); - if (ch == CHAR_EOF) - { - if (!caller) - { - assert (line); - m4_set_current_file (context, file); - m4_set_current_line (context, *line); - } - m4_error (context, EXIT_FAILURE, 0, caller, - _("end of file in string")); - } - if (ch == CHAR_BUILTIN) - init_builtin_token (context, obs, obs ? token : NULL); - else if (ch == CHAR_QUOTE) - append_quote_token (context, obs, token); - else if (MATCH (context, ch, M4_SYNTAX_RQUOTE, - context->syntax->quote.str2, - context->syntax->quote.len2, true)) - { - if (--quote_level == 0) - break; - if (1 < context->syntax->quote.len2) - obstack_grow (obs_safe, context->syntax->quote.str2, - context->syntax->quote.len2); - else - obstack_1grow (obs_safe, ch); - } - else if (MATCH (context, ch, M4_SYNTAX_LQUOTE, - context->syntax->quote.str1, - context->syntax->quote.len1, true)) - { - quote_level++; - if (1 < context->syntax->quote.len1) - obstack_grow (obs_safe, context->syntax->quote.str1, - context->syntax->quote.len1); - else - obstack_1grow (obs_safe, ch); - } - else - obstack_1grow (obs_safe, ch); - } - } - else if (MATCH (context, ch, M4_SYNTAX_BCOMM, - context->syntax->comm.str1, - context->syntax->comm.len1, true)) - { /* COMMENT */ - if (obs && !m4_get_discard_comments_opt (context)) - obs_safe = obs; - if (1 < context->syntax->comm.len1) - obstack_grow (obs_safe, context->syntax->comm.str1, - context->syntax->comm.len1); - else - obstack_1grow (obs_safe, ch); - while (1) - { - /* Start with buffer search for potential end delimiter. */ - size_t len; - const char *buffer = next_buffer (context, &len, false); - if (buffer) - { - const char *p; - if (m4_is_syntax_single_comments (M4SYNTAX)) - p = (char *) memchr (buffer, *context->syntax->comm.str2, - len); - else - { - size_t remaining = len; - assert (context->syntax->comm.len2 == 1); - p = buffer; - while (remaining - && !m4_has_syntax (M4SYNTAX, *p, M4_SYNTAX_ECOMM)) - { - p++; - remaining--; - } - if (!remaining) - p = NULL; - } - if (p) - { - obstack_grow (obs_safe, buffer, p - buffer); - ch = to_uchar (*p); - consume_buffer (context, p - buffer + 1); - } - else - { - obstack_grow (obs_safe, buffer, len); - consume_buffer (context, len); - continue; - } - } - /* Fall back to byte-wise search. */ - else - ch = next_char (context, false, false, false); - if (ch == CHAR_EOF) - { - if (!caller) - { - assert (line); - m4_set_current_file (context, file); - m4_set_current_line (context, *line); - } - m4_error (context, EXIT_FAILURE, 0, caller, - _("end of file in comment")); - } - if (ch == CHAR_BUILTIN) - { - init_builtin_token (context, NULL, NULL); - continue; - } - if (MATCH (context, ch, M4_SYNTAX_ECOMM, - context->syntax->comm.str2, - context->syntax->comm.len2, true)) - { - if (1 < context->syntax->comm.len2) - obstack_grow (obs_safe, context->syntax->comm.str2, - context->syntax->comm.len2); - else - obstack_1grow (obs_safe, ch); - break; - } - assert (ch < CHAR_EOF); - obstack_1grow (obs_safe, ch); - } - type = (m4_get_discard_comments_opt (context) - ? M4_TOKEN_NONE : M4_TOKEN_COMMENT); - } - else if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_ACTIVE)) - { /* ACTIVE CHARACTER */ - obstack_1grow (&token_stack, ch); - type = M4_TOKEN_WORD; - } - else if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_OPEN)) - { /* OPEN PARENTHESIS */ - obstack_1grow (&token_stack, ch); - type = M4_TOKEN_OPEN; - } - else if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_COMMA)) - { /* COMMA */ - obstack_1grow (&token_stack, ch); - type = M4_TOKEN_COMMA; - } - else if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_CLOSE)) - { /* CLOSE PARENTHESIS */ - obstack_1grow (&token_stack, ch); - type = M4_TOKEN_CLOSE; - } - else - { /* EVERYTHING ELSE */ - assert (ch < CHAR_EOF); - obstack_1grow (&token_stack, ch); - if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_OTHER | M4_SYNTAX_NUM)) - { - if (obs) - { - obs_safe = obs; - obstack_1grow (obs, ch); - } - if (m4__safe_quotes (M4SYNTAX)) - consume_syntax (context, obs_safe, - M4_SYNTAX_OTHER | M4_SYNTAX_NUM); - type = M4_TOKEN_STRING; - } - else if (m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_SPACE)) - { - /* Coalescing newlines when interactive or when synclines - are enabled is wrong. */ - if (!m4_get_interactive_opt (context) - && !m4_get_syncoutput_opt (context) - && m4__safe_quotes (M4SYNTAX)) - consume_syntax (context, &token_stack, M4_SYNTAX_SPACE); - type = M4_TOKEN_SPACE; - } - else - type = M4_TOKEN_SIMPLE; - } - } while (type == M4_TOKEN_NONE); - - if (token->type == M4_SYMBOL_VOID) - { - if (obs_safe != obs) - { - len = obstack_object_size (&token_stack); - obstack_1grow (&token_stack, '\0'); - - m4_set_symbol_value_text (token, obstack_finish (&token_stack), len, - m4__quote_age (M4SYNTAX)); - } - else - assert (type == M4_TOKEN_STRING || type == M4_TOKEN_COMMENT); - } - else - assert (token->type == M4_SYMBOL_COMP - && (type == M4_TOKEN_STRING || type == M4_TOKEN_COMMENT)); - VALUE_MAX_ARGS (token) = -1; - -#ifdef DEBUG_INPUT - if (token->type == M4_SYMBOL_VOID) - { - len = obstack_object_size (&token_stack); - obstack_1grow (&token_stack, '\0'); - - m4_set_symbol_value_text (token, obstack_finish (&token_stack), len, - m4__quote_age (M4SYNTAX)); - } - - m4_print_token (context, "next_token", type, token); -#endif - - return type; -} - -/* Peek at the next token in the input stream to see if it is an open - parenthesis. It is possible that what is peeked at may change as a - result of changequote (or friends). This honors multi-character - comments and quotes, just as next_token does. */ -bool -m4__next_token_is_open (m4 *context) -{ - int ch = peek_char (context, false); - - if (ch == CHAR_EOF || ch == CHAR_BUILTIN - || m4_has_syntax (M4SYNTAX, ch, (M4_SYNTAX_BCOMM | M4_SYNTAX_ESCAPE - | M4_SYNTAX_ALPHA | M4_SYNTAX_LQUOTE - | M4_SYNTAX_ACTIVE)) - || (MATCH (context, ch, M4_SYNTAX_BCOMM, context->syntax->comm.str1, - context->syntax->comm.len1, false)) - || (MATCH (context, ch, M4_SYNTAX_LQUOTE, context->syntax->quote.str1, - context->syntax->quote.len1, false))) - return false; - return m4_has_syntax (M4SYNTAX, ch, M4_SYNTAX_OPEN); -} - - -#ifdef DEBUG_INPUT - -int -m4_print_token (m4 *context, const char *s, m4__token_type type, - m4_symbol_value *token) -{ - m4_obstack obs; - size_t len; - - if (!s) - s = "m4input"; - xfprintf (stderr, "%s: ", s); - switch (type) - { /* TOKSW */ - case M4_TOKEN_EOF: - fputs ("eof", stderr); - token = NULL; - break; - case M4_TOKEN_NONE: - fputs ("none", stderr); - token = NULL; - break; - case M4_TOKEN_STRING: - fputs ("string\t", stderr); - break; - case M4_TOKEN_COMMENT: - fputs ("comment\t", stderr); - break; - case M4_TOKEN_SPACE: - fputs ("space\t", stderr); - break; - case M4_TOKEN_WORD: - fputs ("word\t", stderr); - break; - case M4_TOKEN_OPEN: - fputs ("open\t", stderr); - break; - case M4_TOKEN_COMMA: - fputs ("comma\t", stderr); - break; - case M4_TOKEN_CLOSE: - fputs ("close\t", stderr); - break; - case M4_TOKEN_SIMPLE: - fputs ("simple\t", stderr); - break; - case M4_TOKEN_MACDEF: - fputs ("builtin\t", stderr); - break; - case M4_TOKEN_ARGV: - fputs ("argv\t", stderr); - break; - default: - abort (); - } - if (token) - { - obstack_init (&obs); - m4__symbol_value_print (context, token, &obs, NULL, false, NULL, NULL, - true); - len = obstack_object_size (&obs); - xfprintf (stderr, "%s\n", quotearg_style_mem (c_maybe_quoting_style, - obstack_finish (&obs), - len)); - obstack_free (&obs, NULL); - } - else - fputc ('\n', stderr); - return 0; -} -#endif /* DEBUG_INPUT */ diff --git a/m4/m4.c b/m4/m4.c deleted file mode 100644 index 0bf185ce..00000000 --- a/m4/m4.c +++ /dev/null @@ -1,159 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 2001, 2004, 2006-2008, 2010, 2013-2014, 2017 - 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 . -*/ - -#include - -#include "bitrotate.h" -#include "m4private.h" - -#define DEFAULT_NESTING_LIMIT 1024 -#define DEFAULT_NAMEMAP_SIZE 61 - -static size_t -hashfn (const void *ptr) -{ - const char *s = (const char *) ptr; - size_t val = DEFAULT_NAMEMAP_SIZE; - while (*s) - val = rotl_sz (val, 7) + to_uchar (*s++); - return val; -} - - -m4 * -m4_create (void) -{ - m4 *context = (m4 *) xzalloc (sizeof *context); - - context->symtab = m4_symtab_create (0); - context->syntax = m4_syntax_create (); - - context->namemap = - m4_hash_new (DEFAULT_NAMEMAP_SIZE, hashfn, (m4_hash_cmp_func *) strcmp); - - context->debug_file = stderr; - obstack_init (&context->trace_messages); - - context->nesting_limit = DEFAULT_NESTING_LIMIT; - context->debug_level = M4_DEBUG_TRACE_INITIAL; - context->max_debug_arg_length = SIZE_MAX; - - context->search_path = - (m4__search_path_info *) xzalloc (sizeof *context->search_path); - m4__include_init (context); - - return context; -} - -void -m4_delete (m4 *context) -{ - size_t i; - assert (context); - - if (context->symtab) - m4_symtab_delete (context->symtab); - - if (context->syntax) - m4_syntax_delete (context->syntax); - - /* debug_file should have been reset to stdout or stderr, both of - which are closed later. */ - assert (context->debug_file == stderr || context->debug_file == stdout); - - obstack_free (&context->trace_messages, NULL); - - if (context->search_path) - { - m4__search_path *path = context->search_path->list; - - while (path) - { - m4__search_path *stale = path; - path = path->next; - - DELETE (stale->dir); /* Cast away const. */ - free (stale); - } - free (context->search_path); - } - - for (i = 0; i < context->stacks_count; i++) - { - assert (context->arg_stacks[i].refcount == 0 - && context->arg_stacks[i].argcount == 0); - if (context->arg_stacks[i].args) - { - obstack_free (context->arg_stacks[i].args, NULL); - free (context->arg_stacks[i].args); - obstack_free (context->arg_stacks[i].argv, NULL); - free (context->arg_stacks[i].argv); - } - } - free (context->arg_stacks); - - free (context); -} - - - -/* Use the preprocessor to generate the repetitive bit twiddling functions - for us. Note the additional paretheses around the expanded function - name to protect against macro expansion from the fast macros used to - replace these functions when NDEBUG is defined. */ -#define M4FIELD(type, base, field) \ - type (CONC(m4_get_, base)) (m4 *context) \ - { \ - assert (context); \ - return context->field; \ - } -m4_context_field_table -#undef M4FIELD - -#define M4FIELD(type, base, field) \ - type (CONC(m4_set_, base)) (m4 *context, type value) \ - { \ - assert (context); \ - return context->field = value; \ - } -m4_context_field_table -#undef M4FIELD - -#define M4OPT_BIT(bit, base) \ - bool (CONC(m4_get_, base)) (m4 *context) \ - { \ - assert (context); \ - return BIT_TEST (context->opt_flags, (bit)); \ - } -m4_context_opt_bit_table -#undef M4OPT_BIT - -#define M4OPT_BIT(bit, base) \ - bool (CONC(m4_set_, base)) (m4 *context, bool value) \ - { \ - assert (context); \ - if (value) \ - BIT_SET (context->opt_flags, (bit)); \ - else \ - BIT_RESET (context->opt_flags, (bit)); \ - return value; \ - } -m4_context_opt_bit_table -#undef M4OPT_BIT diff --git a/m4/m4module.h b/m4/m4module.h deleted file mode 100644 index a96b9853..00000000 --- a/m4/m4module.h +++ /dev/null @@ -1,556 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 1999-2000, 2003-2010, 2013-2014, 2017 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 . -*/ - -#ifndef M4MODULE_H -#define M4MODULE_H 1 - -#include -#include - -BEGIN_C_DECLS - - - -/* --- MODULE AUTHOR DECLARATIONS --- */ - -typedef struct m4 m4; -typedef struct m4_builtin m4_builtin; -typedef struct m4_call_info m4_call_info; -typedef struct m4_macro m4_macro; -typedef struct m4_macro_args m4_macro_args; -typedef struct m4_module m4_module; -typedef struct obstack m4_obstack; -typedef struct m4_string m4_string; -typedef struct m4_string_pair m4_string_pair; -typedef struct m4_symbol m4_symbol; -typedef struct m4_symbol_value m4_symbol_value; - -typedef void m4_builtin_func (m4 *, m4_obstack *, size_t, m4_macro_args *); - -/* The value of m4_builtin flags is built from these: */ -enum { - /* Set if macro flattens non-text tokens, such as builtin macro - tokens, to the empty string prior to invoking the builtin; if - clear, non-text tokens must be transparently handled by the - builtin. May only be set if max_args is nonzero. */ - M4_BUILTIN_FLATTEN_ARGS = (1 << 0), - /* Set if macro should only be recognized with arguments; may only - be set if min_args is nonzero. */ - M4_BUILTIN_BLIND = (1 << 1), - /* Set if macro has side effects even when there are too few - arguments; may only be set if min_args is nonzero. */ - M4_BUILTIN_SIDE_EFFECT = (1 << 2), - - /* Mask of valid flag bits. Any other bits must be set to 0. */ - M4_BUILTIN_FLAGS_MASK = (1 << 3) - 1 -}; - -struct m4_builtin -{ - m4_builtin_func * func; /* implementation of the builtin */ - const char * name; /* name found by builtin, printed by dumpdef */ - int flags; /* bitwise OR of M4_BUILTIN_* bits */ - size_t min_args; /* 0-based minimum number of arguments */ - /* max arguments, SIZE_MAX if unlimited; must be >= min_args */ - size_t max_args; -}; - -struct m4_macro -{ - const char *name; - const char *value; - size_t min_args; /* 0-based minimum number of arguments */ - /* max arguments, SIZE_MAX if unlimited; must be >= min_args */ - size_t max_args; -}; - -/* Describe a single string, such as a macro name. */ -struct m4_string -{ - char *str; /* Array of characters, possibly including NUL. */ - size_t len; /* Length of string. */ -}; - -/* Describe a pair of strings, such as begin and end quotes. */ -struct m4_string_pair -{ - char *str1; /* First string. */ - size_t len1; /* First length. */ - char *str2; /* Second string. */ - size_t len2; /* Second length. */ -}; - -/* Declare a prototype for the function "builtin_". Note that - the function name includes any macro expansion of NAME. */ -#define M4BUILTIN(name) \ - static void CONC (builtin_, name) \ - (m4 *, m4_obstack *, size_t, m4_macro_args *); - -/* Begin the implementation of the function "builtin_", - declaring parameter names that can be used by other helper macros - in this file. Note that the function name includes any macro - expansion of NAME. */ -#define M4BUILTIN_HANDLER(name) \ - static void CONC (builtin_, name) \ - (m4 *context, m4_obstack *obs, size_t argc, m4_macro_args *argv) - -/* Declare a variable S of type "_func" to be a pointer to the - function named S imported from the module M, or NULL if the import - fails. Note that M and S are intentionally used literally rather - than subjected to macro expansion, in all but the variable name. */ -#define M4_MODULE_IMPORT(M, S) \ - S ## _func *S = (S ## _func *) m4_module_import (context, #M, #S, obs) - -/* Build an entry in a builtin table, for the builtin N implemented by - the function "builtin_" with name NAME. Build the flags from - the appropriate combination of M4_BUILTIN_FLAG_* based on M if the - builtin transparently supports macro tokens, B if it is blind, and - S if it has side effects. Specify that the builtin takes MIN and - MAX arguments. Note that N is subject to macro expansion, and that - NAME is generally used as #N to avoid clashes with builtins named - after a standard function that is defined as a macro. */ -#define M4BUILTIN_ENTRY(N, NAME, M, B, S, MIN, MAX) \ - { \ - CONC (builtin_, N), NAME, \ - (((!(M) && (MAX)) ? M4_BUILTIN_FLATTEN_ARGS : 0) \ - | (((B) && (MIN)) ? M4_BUILTIN_BLIND : 0) \ - | (((S) && (MIN)) ? M4_BUILTIN_SIDE_EFFECT : 0)), \ - MIN, MAX \ - }, - -/* Grab the text contents of argument I, or abort if the argument is - not text. Assumes that `m4 *context' and `m4_macro_args *argv' are - in scope. */ -#define M4ARG(i) m4_arg_text (context, argv, i, false) - -/* Grab the length of the text contents of argument I, or abort if the - argument is not text. Assumes that `m4 *context' and - `m4_macro_args *argv' are in scope. */ -#define M4ARGLEN(i) m4_arg_len (context, argv, i, false) - -extern bool m4_bad_argc (m4 *, size_t, const m4_call_info *, size_t, - size_t, bool); -extern bool m4_numeric_arg (m4 *, const m4_call_info *, const char *, - size_t, int *); -extern bool m4_parse_truth_arg (m4 *, const m4_call_info *, const char *, - size_t, bool); -extern m4_symbol *m4_symbol_value_lookup (m4 *, m4_macro_args *, size_t, bool); -extern const char *m4_info_name (const m4_call_info *); - -/* Error handling. */ -extern void m4_error (m4 *, int, int, const m4_call_info *, const char *, ...) - M4_GNUC_PRINTF (5, 6); -extern void m4_warn (m4 *, int, const m4_call_info *, const char *, ...) - M4_GNUC_PRINTF (4, 5); - -extern const char * m4_get_program_name (void); -extern void m4_set_program_name (const char *); -extern void m4_set_exit_failure (int); - - -/* --- CONTEXT MANAGEMENT --- */ - -typedef struct m4_syntax_table m4_syntax_table; -typedef struct m4_symbol_table m4_symbol_table; - -extern m4 * m4_create (void); -extern void m4_delete (m4 *); - -#define m4_context_field_table \ - M4FIELD(m4_symbol_table *, symbol_table, symtab) \ - M4FIELD(m4_syntax_table *, syntax_table, syntax) \ - M4FIELD(const char *, current_file, current_file) \ - M4FIELD(int, current_line, current_line) \ - M4FIELD(int, output_line, output_line) \ - M4FIELD(FILE *, debug_file, debug_file) \ - M4FIELD(m4_obstack, trace_messages, trace_messages) \ - M4FIELD(int, exit_status, exit_status) \ - M4FIELD(int, current_diversion, current_diversion) \ - M4FIELD(size_t, nesting_limit_opt, nesting_limit) \ - M4FIELD(int, debug_level_opt, debug_level) \ - M4FIELD(size_t, max_debug_arg_length_opt, max_debug_arg_length)\ - M4FIELD(int, regexp_syntax_opt, regexp_syntax) \ - - -#define m4_context_opt_bit_table \ - M4OPT_BIT(M4_OPT_PREFIX_BUILTINS_BIT, prefix_builtins_opt) \ - M4OPT_BIT(M4_OPT_SUPPRESS_WARN_BIT, suppress_warnings_opt) \ - M4OPT_BIT(M4_OPT_DISCARD_COMMENTS_BIT, discard_comments_opt) \ - M4OPT_BIT(M4_OPT_INTERACTIVE_BIT, interactive_opt) \ - M4OPT_BIT(M4_OPT_SYNCOUTPUT_BIT, syncoutput_opt) \ - M4OPT_BIT(M4_OPT_POSIXLY_CORRECT_BIT, posixly_correct_opt) \ - M4OPT_BIT(M4_OPT_FATAL_WARN_BIT, fatal_warnings_opt) \ - M4OPT_BIT(M4_OPT_WARN_EXIT_BIT, warnings_exit_opt) \ - M4OPT_BIT(M4_OPT_SAFER_BIT, safer_opt) \ - - -#define M4FIELD(type, base, field) \ - extern type CONC (m4_get_, base) (m4 *context); \ - extern type CONC (m4_set_, base) (m4 *context, type value); -m4_context_field_table -#undef M4FIELD - -#define M4OPT_BIT(bit, base) \ - extern bool CONC (m4_get_, base) (m4 *context); \ - extern bool CONC (m4_set_, base) (m4 *context, bool value); -m4_context_opt_bit_table -#undef M4OPT_BIT - -#define M4SYMTAB (m4_get_symbol_table (context)) -#define M4SYNTAX (m4_get_syntax_table (context)) - - - -/* --- MODULE MANAGEMENT --- */ - -typedef void m4_module_init_func (m4 *, m4_module *, m4_obstack *); - -extern m4_module * m4_module_load (m4 *, const char *, m4_obstack *); -extern void * m4_module_import (m4 *, const char *, const char *, - m4_obstack *); - -extern void m4_install_builtins (m4*, m4_module *, const m4_builtin*); -extern void m4_install_macros (m4*, m4_module *, const m4_macro*); - -extern const char * m4_get_module_name (const m4_module *); -extern m4_module * m4_module_next (m4*, m4_module *); - - - -/* --- SYMBOL TABLE MANAGEMENT --- */ - - -typedef void *m4_symtab_apply_func (m4_symbol_table *, const char *, size_t, - m4_symbol *, void *); - -extern m4_symbol_table *m4_symtab_create (size_t); -extern void m4_symtab_delete (m4_symbol_table *); -extern void * m4_symtab_apply (m4_symbol_table *, bool, - m4_symtab_apply_func *, void *); - -extern m4_symbol *m4_symbol_lookup (m4_symbol_table *, const char *, size_t); -extern m4_symbol *m4_symbol_pushdef (m4_symbol_table *, const char *, size_t, - m4_symbol_value *); -extern m4_symbol *m4_symbol_define (m4_symbol_table *, const char *, size_t, - m4_symbol_value *); -extern void m4_symbol_popdef (m4_symbol_table *, const char *, size_t); -extern m4_symbol *m4_symbol_rename (m4_symbol_table *, const char *, size_t, - const char *, size_t); - -extern void m4_symbol_delete (m4_symbol_table *, const char *, size_t); - -#define m4_symbol_delete(symtab, name, len) M4_STMT_START \ - { \ - while (m4_symbol_lookup (symtab, name, len)) \ - m4_symbol_popdef (symtab, name, len); \ - } M4_STMT_END - -extern m4_symbol_value *m4_get_symbol_value (m4_symbol *); -extern bool m4_get_symbol_traced (m4_symbol *); -extern bool m4_set_symbol_name_traced (m4_symbol_table *, - const char *, size_t, bool); -extern void m4_symbol_print (m4 *, m4_symbol *, m4_obstack *, - const m4_string_pair *, bool, size_t, - bool); -extern bool m4_symbol_value_flatten_args (m4_symbol_value *); - -#define m4_is_symbol_void(symbol) \ - (m4_is_symbol_value_void (m4_get_symbol_value (symbol))) -#define m4_is_symbol_text(symbol) \ - (m4_is_symbol_value_text (m4_get_symbol_value (symbol))) -#define m4_is_symbol_func(symbol) \ - (m4_is_symbol_value_func (m4_get_symbol_value (symbol))) -#define m4_is_symbol_placeholder(symbol) \ - (m4_is_symbol_value_placeholder (m4_get_symbol_value (symbol))) -#define m4_get_symbol_text(symbol) \ - (m4_get_symbol_value_text (m4_get_symbol_value (symbol))) -#define m4_get_symbol_len(symbol) \ - (m4_get_symbol_value_len (m4_get_symbol_value (symbol))) -#define m4_get_symbol_func(symbol) \ - (m4_get_symbol_value_func (m4_get_symbol_value (symbol))) -#define m4_get_symbol_builtin(symbol) \ - (m4_get_symbol_value_builtin (m4_get_symbol_value (symbol))) -#define m4_get_symbol_placeholder(symbol) \ - (m4_get_symbol_value_placeholder (m4_get_symbol_value (symbol))) -#define m4_symbol_flatten_args(symbol) \ - (m4_symbol_value_flatten_args (m4_get_symbol_value (symbol))) - -extern m4_symbol_value *m4_symbol_value_create (void); -extern void m4_symbol_value_delete (m4_symbol_value *); -extern bool m4_symbol_value_copy (m4 *, m4_symbol_value *, - m4_symbol_value *); -extern bool m4_is_symbol_value_text (m4_symbol_value *); -extern bool m4_is_symbol_value_func (m4_symbol_value *); -extern bool m4_is_symbol_value_placeholder (m4_symbol_value *); -extern bool m4_is_symbol_value_void (m4_symbol_value *); - -extern const char * m4_get_symbol_value_text (m4_symbol_value *); -extern size_t m4_get_symbol_value_len (m4_symbol_value *); -extern unsigned int m4_get_symbol_value_quote_age (m4_symbol_value *); - -extern m4_builtin_func *m4_get_symbol_value_func (m4_symbol_value *); -extern const m4_builtin *m4_get_symbol_value_builtin (m4_symbol_value *); -extern const char * m4_get_symbol_value_placeholder (m4_symbol_value *); - -extern void m4_set_symbol_value_text (m4_symbol_value *, - const char *, size_t, - unsigned int); -extern void m4_set_symbol_value_placeholder (m4_symbol_value *, - const char *); - - - -/* --- BUILTIN MANAGEMENT --- */ - -extern m4_symbol_value *m4_builtin_find_by_name (m4 *, m4_module *, const char *); -extern m4_symbol_value *m4_builtin_find_by_func (m4 *, m4_module *, - m4_builtin_func *); - - - -/* --- MACRO MANAGEMENT --- */ - -extern void m4_macro_expand_input (m4 *); -extern void m4_macro_call (m4 *, m4_symbol_value *, m4_obstack *, - m4_macro_args *); -extern size_t m4_arg_argc (m4_macro_args *); -extern const m4_call_info *m4_arg_info (m4_macro_args *); -extern m4_symbol_value *m4_arg_symbol (m4_macro_args *, size_t); -extern bool m4_is_arg_text (m4_macro_args *, size_t); -extern bool m4_is_arg_func (m4_macro_args *, size_t); -extern bool m4_is_arg_composite (m4_macro_args *, size_t); -extern const char *m4_arg_text (m4 *, m4_macro_args *, size_t, bool); -extern bool m4_arg_equal (m4 *, m4_macro_args *, size_t, - size_t); -extern bool m4_arg_empty (m4_macro_args *, size_t); -extern size_t m4_arg_len (m4 *, m4_macro_args *, size_t, bool); -extern m4_builtin_func *m4_arg_func (m4_macro_args *, size_t); -extern m4_obstack *m4_arg_scratch (m4 *); -extern m4_macro_args *m4_make_argv_ref (m4 *, m4_macro_args *, const char *, - size_t, bool, bool); -extern void m4_push_arg (m4 *, m4_obstack *, m4_macro_args *, - size_t); -extern void m4_push_args (m4 *, m4_obstack *, m4_macro_args *, - bool, bool); -extern void m4_wrap_args (m4 *, m4_macro_args *); - - -/* --- RUNTIME DEBUGGING --- */ - -/* The value of debug_level is a bitmask of the following: */ -enum { - /* a: show arglist in trace output */ - M4_DEBUG_TRACE_ARGS = (1 << 0), - /* e: show expansion in trace output */ - M4_DEBUG_TRACE_EXPANSION = (1 << 1), - /* q: quote args and expansion in trace output */ - M4_DEBUG_TRACE_QUOTE = (1 << 2), - /* t: trace all macros -- overrides trace{on,off} */ - M4_DEBUG_TRACE_ALL = (1 << 3), - /* l: add line numbers to trace output */ - M4_DEBUG_TRACE_LINE = (1 << 4), - /* f: add file name to trace output */ - M4_DEBUG_TRACE_FILE = (1 << 5), - /* p: trace path search of include files */ - M4_DEBUG_TRACE_PATH = (1 << 6), - /* c: show macro call before args collection */ - M4_DEBUG_TRACE_CALL = (1 << 7), - /* i: trace changes of input files */ - M4_DEBUG_TRACE_INPUT = (1 << 8), - /* x: add call id to trace output */ - M4_DEBUG_TRACE_CALLID = (1 << 9), - /* m: trace module actions */ - M4_DEBUG_TRACE_MODULE = (1 << 10), - /* s: trace pushdef stacks */ - M4_DEBUG_TRACE_STACK = (1 << 11), - /* d: warn if dereferencing undefined macro */ - M4_DEBUG_TRACE_DEREF = (1 << 12), - /* o: output dumpdef to stderr, not debug file */ - M4_DEBUG_TRACE_OUTPUT_DUMPDEF = (1 << 13), - - /* V: very verbose -- print everything */ - M4_DEBUG_TRACE_VERBOSE = ((1 << 14) - 1) -}; - -/* initial flags, used if no -d or -E -- equiv: d */ -#define M4_DEBUG_TRACE_INITIAL M4_DEBUG_TRACE_DEREF - -/* default flags, used by debugmode() -- equiv: +adeq */ -#define M4_DEBUG_TRACE_DEFAULT \ - (M4_DEBUG_TRACE_ARGS | M4_DEBUG_TRACE_EXPANSION \ - | M4_DEBUG_TRACE_QUOTE | M4_DEBUG_TRACE_DEREF) - -#define m4_is_debug_bit(C,B) ((m4_get_debug_level_opt (C) & (B)) != 0) - -extern int m4_debug_decode (m4 *, const char *, size_t); -extern bool m4_debug_set_output (m4 *, const m4_call_info *, - const char *); -extern void m4_debug_message_prefix (m4 *); -extern void m4_debug_message (m4 *, int, const char *, ...) - M4_GNUC_PRINTF (3, 4); - -extern void m4_trace_prepare (m4 *, const m4_call_info *, - m4_symbol_value *); - - -/* --- REGEXP SYNTAX --- */ - -extern const char * m4_regexp_syntax_decode (int); -extern int m4_regexp_syntax_encode (const char *); - - - -/* --- SYNTAX TABLE DEFINITIONS --- */ - -extern m4_syntax_table *m4_syntax_create (void); -extern void m4_syntax_delete (m4_syntax_table *syntax); -extern int m4_syntax_code (char ch); - -extern const char * m4_get_syntax_lquote (m4_syntax_table *syntax); -extern const char * m4_get_syntax_rquote (m4_syntax_table *syntax); -extern const char * m4_get_syntax_bcomm (m4_syntax_table *syntax); -extern const char * m4_get_syntax_ecomm (m4_syntax_table *syntax); -extern const m4_string_pair *m4_get_syntax_quotes (m4_syntax_table *); -extern const m4_string_pair *m4_get_syntax_comments (m4_syntax_table *); - -extern bool m4_is_syntax_single_quotes (m4_syntax_table *); -extern bool m4_is_syntax_single_comments (m4_syntax_table *); -extern bool m4_is_syntax_single_dollar (m4_syntax_table *); -extern bool m4_is_syntax_macro_escaped (m4_syntax_table *); - -/* These are values to be assigned to syntax table entries. Although - they are bit masks for fast categorization in m4__next_token(), - only one value per syntax table entry is allowed. The enumeration - is currently sorted in order of parsing precedence. */ -enum { - M4_SYNTAX_IGNORE = 0, - M4_SYNTAX_ESCAPE = 1 << 0, - M4_SYNTAX_ALPHA = 1 << 1, - M4_SYNTAX_LQUOTE = 1 << 2, - M4_SYNTAX_BCOMM = 1 << 3, - M4_SYNTAX_ACTIVE = 1 << 4, - M4_SYNTAX_NUM = 1 << 5, - M4_SYNTAX_SPACE = 1 << 6, - M4_SYNTAX_OPEN = 1 << 7, - M4_SYNTAX_CLOSE = 1 << 8, - M4_SYNTAX_COMMA = 1 << 9, - M4_SYNTAX_OTHER = 1 << 10, - - /* These values are bit masks to OR with categories above, a syntax entry - may have any number of these in addition to a maximum of one of the - values above. */ - M4_SYNTAX_DOLLAR = 1 << 11, - M4_SYNTAX_LBRACE = 1 << 12, - M4_SYNTAX_RBRACE = 1 << 13, - M4_SYNTAX_RQUOTE = 1 << 14, - M4_SYNTAX_ECOMM = 1 << 15 -}; - -/* Mask of attribute syntax categories. */ -#define M4_SYNTAX_MASKS (M4_SYNTAX_RQUOTE | M4_SYNTAX_ECOMM \ - | M4_SYNTAX_DOLLAR | M4_SYNTAX_LBRACE \ - | M4_SYNTAX_RBRACE) -/* Mask of basic syntax categories where any change requires a - recomputation of the overall syntax characteristics. */ -#define M4_SYNTAX_SUSPECT (M4_SYNTAX_LQUOTE | M4_SYNTAX_BCOMM \ - | M4_SYNTAX_ESCAPE) - -#define m4_syntab(S, C) ((S)->table[(C)]) -/* Determine if character C matches any of the bitwise-or'd syntax - categories T for the given syntax table S. C can be either an - unsigned int (including special values such as CHAR_BUILTIN) or a - char which will be interpreted as an unsigned char. */ -#define m4_has_syntax(S, C, T) \ - ((m4_syntab ((S), sizeof (C) == 1 ? to_uchar (C) : (C)) & (T)) > 0) - -extern void m4_set_quotes (m4_syntax_table *, const char *, size_t, - const char *, size_t); -extern void m4_set_comment (m4_syntax_table *, const char *, size_t, - const char *, size_t); -extern int m4_set_syntax (m4_syntax_table *, char, char, const char *, - size_t); -extern void m4_reset_syntax (m4_syntax_table *); - - - -/* --- INPUT TOKENIZATION --- */ - -extern void m4_input_init (m4 *context); -extern void m4_input_exit (void); -extern void m4_skip_line (m4 *context, const m4_call_info *); - -/* push back input */ - -extern void m4_push_file (m4 *, FILE *, const char *, bool); -extern void m4_push_builtin (m4 *, m4_obstack *, m4_symbol_value *); -extern m4_obstack *m4_push_string_init (m4 *, const char *, int); -extern void m4_push_string_finish (void); -extern bool m4_pop_wrapup (m4 *); -extern void m4_input_print (m4 *, m4_obstack *, int); - - - -/* --- OUTPUT MANAGEMENT --- */ - -extern void m4_output_init (m4 *); -extern void m4_output_exit (void); -extern void m4_output_text (m4 *, const char *, size_t); -extern void m4_divert_text (m4 *, m4_obstack *, const char *, - size_t, int); -extern void m4_shipout_int (m4_obstack *, int); -extern void m4_shipout_string (m4 *, m4_obstack *, const char *, - size_t, bool); -extern bool m4_shipout_string_trunc (m4_obstack *, const char *, size_t, - const m4_string_pair *, size_t *); - -extern void m4_make_diversion (m4 *, int); -extern void m4_insert_diversion (m4 *, int); -extern void m4_insert_file (m4 *, FILE *); -extern void m4_freeze_diversions (m4 *, FILE *); -extern void m4_undivert_all (m4 *); - - - -/* --- PATH MANAGEMENT --- */ - -extern void m4_add_include_directory (m4 *, const char *, bool); -extern bool m4_load_filename (m4 *, const m4_call_info *, - const char *, m4_obstack *, bool); -extern char * m4_path_search (m4 *, const char *, const char **); -extern FILE * m4_fopen (m4 *, const char *, const char *); - - - -#define obstack_chunk_alloc xmalloc -#define obstack_chunk_free free - - -/* Convert a possibly-signed character to an unsigned character. This is - a bit safer than casting to unsigned char, since it catches some type - errors that the cast doesn't. */ -#if HAVE_INLINE -static inline unsigned char to_uchar (char ch) { return ch; } -#else -# define to_uchar(C) ((unsigned char) (C)) -#endif - -END_C_DECLS - -#endif /* !M4MODULE_H */ diff --git a/m4/m4private.h b/m4/m4private.h deleted file mode 100644 index a09ca9f8..00000000 --- a/m4/m4private.h +++ /dev/null @@ -1,626 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 1998-1999, 2004-2010, 2013-2014, 2017 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 . -*/ - -#ifndef M4PRIVATE_H -#define M4PRIVATE_H 1 - -#include - -#include "cloexec.h" -#include "quotearg.h" -#include "xmemdup0.h" - -typedef struct m4__search_path_info m4__search_path_info; -typedef struct m4__macro_arg_stacks m4__macro_arg_stacks; -typedef struct m4__symbol_chain m4__symbol_chain; - -typedef enum { - M4_SYMBOL_VOID, /* Traced but undefined, u is invalid. */ - M4_SYMBOL_TEXT, /* Plain text, u.u_t is valid. */ - M4_SYMBOL_FUNC, /* Builtin function, u.func is valid. */ - M4_SYMBOL_PLACEHOLDER, /* Placeholder for unknown builtin from -R. */ - M4_SYMBOL_COMP /* Composite symbol, u.u_c.c is valid. */ -} m4__symbol_type; - -#define BIT_TEST(flags, bit) (((flags) & (bit)) == (bit)) -#define BIT_SET(flags, bit) ((flags) |= (bit)) -#define BIT_RESET(flags, bit) ((flags) &= ~(bit)) - -/* Gnulib's stdbool doesn't work with bool bitfields. For nicer - debugging, use bool when we know it works, but use the more - portable unsigned int elsewhere. */ -#if __GNUC__ > 2 -typedef bool bool_bitfield; -#else -typedef unsigned int bool_bitfield; -#endif /* !__GNUC__ */ - - -/* --- CONTEXT MANAGEMENT --- */ - -struct m4 { - m4_symbol_table * symtab; - m4_syntax_table * syntax; - m4_module * modules; - m4_hash * namemap; - - const char * current_file; /* Current input file. */ - int current_line; /* Current input line. */ - int output_line; /* Current output line. */ - - FILE * debug_file; /* File for debugging output. */ - m4_obstack trace_messages; - int exit_status; /* Cumulative exit status. */ - int current_diversion; /* Current output diversion. */ - - /* Option flags (set in src/main.c). */ - size_t nesting_limit; /* -L */ - int debug_level; /* -d */ - size_t max_debug_arg_length; /* -l */ - int regexp_syntax; /* -r */ - int opt_flags; - - /* __PRIVATE__: */ - m4__search_path_info *search_path; /* The list of path directories. */ - m4__macro_arg_stacks *arg_stacks; /* Array of current argv refs. */ - size_t stacks_count; /* Size of arg_stacks. */ - size_t expansion_level;/* Macro call nesting level. */ -}; - -#define M4_OPT_PREFIX_BUILTINS_BIT (1 << 0) /* -P */ -#define M4_OPT_SUPPRESS_WARN_BIT (1 << 1) /* -Q */ -#define M4_OPT_DISCARD_COMMENTS_BIT (1 << 2) /* -c */ -#define M4_OPT_INTERACTIVE_BIT (1 << 3) /* -e */ -#define M4_OPT_SYNCOUTPUT_BIT (1 << 4) /* -s */ -#define M4_OPT_POSIXLY_CORRECT_BIT (1 << 5) /* -G/POSIXLY_CORRECT */ -#define M4_OPT_FATAL_WARN_BIT (1 << 6) /* -E once */ -#define M4_OPT_WARN_EXIT_BIT (1 << 7) /* -E twice */ -#define M4_OPT_SAFER_BIT (1 << 8) /* --safer */ - -/* Fast macro versions of accessor functions for public fields of m4, - that also have an identically named function exported in m4module.h. */ -#ifdef NDEBUG -# define m4_get_symbol_table(C) ((C)->symtab) -# define m4_set_symbol_table(C, V) ((C)->symtab = (V)) -# define m4_get_syntax_table(C) ((C)->syntax) -# define m4_set_syntax_table(C, V) ((C)->syntax = (V)) -# define m4_get_current_file(C) ((C)->current_file) -# define m4_set_current_file(C, V) ((C)->current_file = (V)) -# define m4_get_current_line(C) ((C)->current_line) -# define m4_set_current_line(C, V) ((C)->current_line = (V)) -# define m4_get_output_line(C) ((C)->output_line) -# define m4_set_output_line(C, V) ((C)->output_line = (V)) -# define m4_get_debug_file(C) ((C)->debug_file) -# define m4_set_debug_file(C, V) ((C)->debug_file = (V)) -# define m4_get_trace_messages(C) ((C)->trace_messages) -# define m4_set_trace_messages(C, V) ((C)->trace_messages = (V)) -# define m4_get_exit_status(C) ((C)->exit_status) -# define m4_set_exit_status(C, V) ((C)->exit_status = (V)) -# define m4_get_current_diversion(C) ((C)->current_diversion) -# define m4_set_current_diversion(C, V) ((C)->current_diversion = (V)) -# define m4_get_nesting_limit_opt(C) ((C)->nesting_limit) -# define m4_set_nesting_limit_opt(C, V) ((C)->nesting_limit = (V)) -# define m4_get_debug_level_opt(C) ((C)->debug_level) -# define m4_set_debug_level_opt(C, V) ((C)->debug_level = (V)) -# define m4_get_max_debug_arg_length_opt(C) ((C)->max_debug_arg_length) -# define m4_set_max_debug_arg_length_opt(C, V) ((C)->max_debug_arg_length=(V)) -# define m4_get_regexp_syntax_opt(C) ((C)->regexp_syntax) -# define m4_set_regexp_syntax_opt(C, V) ((C)->regexp_syntax = (V)) - -# define m4_get_prefix_builtins_opt(C) \ - (BIT_TEST((C)->opt_flags, M4_OPT_PREFIX_BUILTINS_BIT)) -# define m4_get_suppress_warnings_opt(C) \ - (BIT_TEST((C)->opt_flags, M4_OPT_SUPPRESS_WARN_BIT)) -# define m4_get_discard_comments_opt(C) \ - (BIT_TEST((C)->opt_flags, M4_OPT_DISCARD_COMMENTS_BIT)) -# define m4_get_interactive_opt(C) \ - (BIT_TEST((C)->opt_flags, M4_OPT_INTERACTIVE_BIT)) -# define m4_get_syncoutput_opt(C) \ - (BIT_TEST((C)->opt_flags, M4_OPT_SYNCOUTPUT_BIT)) -# define m4_get_posixly_correct_opt(C) \ - (BIT_TEST((C)->opt_flags, M4_OPT_POSIXLY_CORRECT_BIT)) -# define m4_get_fatal_warnings_opt(C) \ - (BIT_TEST((C)->opt_flags, M4_OPT_FATAL_WARN_BIT)) -# define m4_get_warnings_exit_opt(C) \ - (BIT_TEST((C)->opt_flags, M4_OPT_WARN_EXIT_BIT)) -# define m4_get_safer_opt(C) \ - (BIT_TEST((C)->opt_flags, M4_OPT_SAFER_BIT)) - -/* No fast opt bit set macros, as they would need to evaluate their - arguments more than once, which would subtly change their semantics. */ -#endif - -/* Accessors for private fields of m4, which have no function version - exported in m4module.h. */ -#define m4__get_search_path(C) ((C)->search_path) - - -/* --- BUILTIN MANAGEMENT --- */ - -/* Internal representation of loaded builtins. */ -struct m4__builtin -{ - /* Copied from module's BUILTIN_SYMBOL table, although builtin.flags - can be used for additional bits beyond what is allowed for - modules. */ - m4_builtin builtin; - m4_module *module; /* Module that owns this builtin. */ -}; -typedef struct m4__builtin m4__builtin; - -extern void m4__set_symbol_value_builtin (m4_symbol_value *, - const m4__builtin *); -extern void m4__builtin_print (m4_obstack *, const m4__builtin *, bool, - m4__symbol_chain **, const m4_string_pair *, - bool); - - -/* --- MODULE MANAGEMENT --- */ - -/* Representation of a loaded m4 module. */ -struct m4_module -{ - const char *name; /* Name of the module. */ - void *handle; /* System module handle. */ - m4__builtin *builtins; /* Sorted array of builtins. */ - m4_macro *macros; /* Unsorted array of macros. */ - size_t builtins_len; /* Number of builtins. */ - m4_module *next; -}; - -extern m4_module * m4__module_open (m4 *context, const char *name, - m4_obstack *obs); -extern m4_module * m4__module_find (m4 *context, const char *name); - - -/* --- SYMBOL TABLE MANAGEMENT --- */ - -struct m4_symbol -{ - bool traced; /* True if this symbol is traced. */ - m4_symbol_value *value; /* Linked list of pushdef'd values. */ -}; - -/* Type of a link in a symbol chain. */ -enum m4__symbol_chain_type -{ - M4__CHAIN_STR, /* Link contains a string, u.u_s is valid. */ - M4__CHAIN_FUNC, /* Link contains builtin token, u.builtin is valid. */ - M4__CHAIN_ARGV, /* Link contains a $@ reference, u.u_a is valid. */ - M4__CHAIN_LOC /* Link contains m4wrap location, u.u_l is valid. */ -}; - -/* Composite symbols are built of a linked list of chain objects. */ -struct m4__symbol_chain -{ - m4__symbol_chain *next; /* Pointer to next link of chain. */ - enum m4__symbol_chain_type type; /* Type of this link. */ - unsigned int quote_age; /* Quote_age of this link, or 0. */ - union - { - struct - { - const char *str; /* Pointer to text. */ - size_t len; /* Remaining length of str. */ - size_t level; /* Expansion level of content, or SIZE_MAX. */ - } u_s; /* M4__CHAIN_STR. */ - const m4__builtin *builtin; /* M4__CHAIN_FUNC. */ - struct - { - m4_macro_args *argv; /* Reference to earlier $@. */ - size_t index; /* Argument index within argv. */ - bool_bitfield flatten : 1; /* True to treat builtins as text. */ - bool_bitfield comma : 1; /* True when `,' is next input. */ - bool_bitfield skip_last : 1; /* True if last argument omitted. */ - bool_bitfield has_func : 1; /* True if argv includes func. */ - const m4_string_pair *quotes; /* NULL for $*, quotes for $@. */ - } u_a; /* M4__CHAIN_ARGV. */ - struct - { - const char *file; /* File where subsequent links originate. */ - int line; /* Line where subsequent links originate. */ - } u_l; /* M4__CHAIN_LOC. */ - } u; -}; - -/* A symbol value is used both for values associated with a macro - name, and for arguments to a macro invocation. */ -struct m4_symbol_value -{ - m4_symbol_value * next; - m4_module * module; - unsigned int flags; - - m4_hash * arg_signature; - size_t min_args; - size_t max_args; - size_t pending_expansions; - - m4__symbol_type type; - union - { - struct - { - size_t len; /* Length of string. */ - const char * text; /* String contents. */ - /* Quote age when this string was built, or zero to force a - rescan of the string. Ignored for 0 len. */ - unsigned int quote_age; - } u_t; /* Valid when type is TEXT, PLACEHOLDER. */ - const m4__builtin * builtin;/* Valid when type is FUNC. */ - struct - { - m4__symbol_chain *chain; /* First link of the chain. */ - m4__symbol_chain *end; /* Last link of the chain. */ - bool_bitfield wrapper : 1; /* True if this is a $@ ref. */ - bool_bitfield has_func : 1; /* True if chain includes func. */ - } u_c; /* Valid when type is COMP. */ - } u; -}; - -/* Structure describing all arguments to a macro, including the macro - name at index 0. */ -struct m4_macro_args -{ - /* One more than the highest actual argument. May be larger than - arraylen since the array can refer to multiple arguments via a - single $@ reference. */ - size_t argc; - /* False unless the macro expansion refers to $@; determines whether - this object can be freed at end of macro expansion or must wait - until all references have been rescanned. */ - bool_bitfield inuse : 1; - /* False if all arguments are just text or func, true if this argv - refers to another one. */ - bool_bitfield wrapper : 1; - /* False if all arguments belong to this argv, true if some of them - include references to another. */ - bool_bitfield has_ref : 1; - /* True to flatten builtins contained in references. */ - bool_bitfield flatten : 1; - /* True if any token contains builtins. */ - bool_bitfield has_func : 1; - /* The value of quote_age for all tokens, or 0 if quote_age changed - during parsing or any token is potentially unsafe and requires a - rescan. */ - unsigned int quote_age; - /* The context of the macro call during expansion, and NULL in a - back-reference. */ - m4_call_info *info; - size_t level; /* Which obstack owns this argv. */ - size_t arraylen; /* True length of allocated elements in array. */ - /* Used as a variable-length array, storing information about each - argument. */ - m4_symbol_value *array[FLEXIBLE_ARRAY_MEMBER]; -}; - -/* Internal structure for managing multiple argv references. See - macro.c for a much more detailed comment on usage. */ -struct m4__macro_arg_stacks -{ - size_t refcount; /* Number of active $@ references at this level. */ - size_t argcount; /* Number of argv at this level. */ - m4_obstack *args; /* Content of arguments. */ - m4_obstack *argv; /* Argv pointers into args. */ - void *args_base; /* Location for clearing the args obstack. */ - void *argv_base; /* Location for clearing the argv obstack. */ -}; - -/* Opaque structure for managing call context information. Contains - the context used in tracing and error messages that was valid at - the start of the macro expansion, even if argument collection - changes global context in the meantime. */ -struct m4_call_info -{ - const char *file; /* The file containing the macro invocation. */ - int line; /* The line the macro was called on. */ - size_t call_id; /* The unique sequence call id of the macro. */ - int trace : 1; /* True to trace this macro. */ - int debug_level : 31; /* The debug level for tracing the macro call. */ - const char *name; /* The macro name. */ - size_t name_len; /* The length of name. */ -}; - -extern size_t m4__adjust_refcount (m4 *, size_t, bool); -extern bool m4__arg_adjust_refcount (m4 *, m4_macro_args *, bool); -extern void m4__push_arg_quote (m4 *, m4_obstack *, m4_macro_args *, - size_t, const m4_string_pair *); -extern bool m4__arg_print (m4 *, m4_obstack *, m4_macro_args *, - size_t, const m4_string_pair *, bool, - m4__symbol_chain **, const char *, - size_t *, bool, bool); - -#define VALUE_NEXT(T) ((T)->next) -#define VALUE_MODULE(T) ((T)->module) -#define VALUE_FLAGS(T) ((T)->flags) -#define VALUE_ARG_SIGNATURE(T) ((T)->arg_signature) -#define VALUE_MIN_ARGS(T) ((T)->min_args) -#define VALUE_MAX_ARGS(T) ((T)->max_args) -#define VALUE_PENDING(T) ((T)->pending_expansions) - -#define SYMBOL_NEXT(S) (VALUE_NEXT ((S)->value)) -#define SYMBOL_MODULE(S) (VALUE_MODULE ((S)->value)) -#define SYMBOL_FLAGS(S) (VALUE_FLAGS ((S)->value)) -#define SYMBOL_ARG_SIGNATURE(S) (VALUE_ARG_SIGNATURE ((S)->value)) -#define SYMBOL_MIN_ARGS(S) (VALUE_MIN_ARGS ((S)->value)) -#define SYMBOL_MAX_ARGS(S) (VALUE_MAX_ARGS ((S)->value)) -#define SYMBOL_PENDING(S) (VALUE_PENDING ((S)->value)) - -/* Fast macro versions of symbol table accessor functions, - that also have an identically named function exported in m4module.h. */ -#ifdef NDEBUG -# define m4_get_symbol_traced(S) ((S)->traced) -# define m4_get_symbol_value(S) ((S)->value) -# define m4_set_symbol_value(S, V) ((S)->value = (V)) - -/* m4_symbol_value_{create,delete} are too complex for a simple macro. */ - -# define m4_is_symbol_value_text(V) ((V)->type == M4_SYMBOL_TEXT) -# define m4_is_symbol_value_func(V) ((V)->type == M4_SYMBOL_FUNC) -# define m4_is_symbol_value_void(V) ((V)->type == M4_SYMBOL_VOID) -# define m4_is_symbol_value_placeholder(V) \ - ((V)->type == M4_SYMBOL_PLACEHOLDER) -# define m4_get_symbol_value_text(V) ((V)->u.u_t.text) -# define m4_get_symbol_value_len(V) ((V)->u.u_t.len) -# define m4_get_symbol_value_quote_age(V) ((V)->u.u_t.quote_age) -# define m4_get_symbol_value_func(V) ((V)->u.builtin->builtin.func) -# define m4_get_symbol_value_builtin(V) (&(V)->u.builtin->builtin) -# define m4_get_symbol_value_placeholder(V) \ - ((V)->u.u_t.text) -# define m4_symbol_value_flatten_args(V) \ - (BIT_TEST ((V)->flags, VALUE_FLATTEN_ARGS_BIT)) - -# define m4_set_symbol_value_text(V, T, L, A) \ - ((V)->type = M4_SYMBOL_TEXT, (V)->u.u_t.text = (T), \ - (V)->u.u_t.len = (L), (V)->u.u_t.quote_age = (A)) -# define m4_set_symbol_value_placeholder(V, T) \ - ((V)->type = M4_SYMBOL_PLACEHOLDER, (V)->u.u_t.text = (T)) -# define m4__set_symbol_value_builtin(V, B) \ - ((V)->type = M4_SYMBOL_FUNC, (V)->u.builtin = (B), \ - VALUE_MODULE (V) = (B)->module, \ - VALUE_FLAGS (V) = (B)->builtin.flags, \ - VALUE_MIN_ARGS (V) = (B)->builtin.min_args, \ - VALUE_MAX_ARGS (V) = (B)->builtin.max_args) -#endif - - - -/* m4_symbol_value.flags bit masks. Be sure these are a consistent - superset of the M4_BUILTIN_* bit masks, so we can copy - m4_builtin.flags to m4_symbol_arg.flags. We can use additional - bits for private use. */ - -#define VALUE_FLATTEN_ARGS_BIT (1 << 0) -#define VALUE_BLIND_ARGS_BIT (1 << 1) -#define VALUE_SIDE_EFFECT_ARGS_BIT (1 << 2) -#define VALUE_DELETED_BIT (1 << 3) - - -struct m4_symbol_arg { - int index; - int flags; - char * default_val; -}; - -#define SYMBOL_ARG_INDEX(A) ((A)->index) -#define SYMBOL_ARG_FLAGS(A) ((A)->flags) -#define SYMBOL_ARG_DEFAULT(A) ((A)->default_val) - -/* m4_symbol_arg.flags bit masks: */ - -#define SYMBOL_ARG_REST_BIT (1 << 0) -#define SYMBOL_ARG_KEY_BIT (1 << 1) - -extern void m4__symtab_remove_module_references (m4_symbol_table *, - m4_module *); -extern bool m4__symbol_value_print (m4 *, m4_symbol_value *, m4_obstack *, - const m4_string_pair *, bool, - m4__symbol_chain **, size_t *, bool); - - - -/* --- SYNTAX TABLE MANAGEMENT --- */ - -/* CHAR_RETRY must be last, because we size the syntax table to hold - all other characters and sentinels. */ -#define CHAR_EOF (UCHAR_MAX + 1) /* Return on EOF. */ -#define CHAR_BUILTIN (UCHAR_MAX + 2) /* Return for BUILTIN token. */ -#define CHAR_QUOTE (UCHAR_MAX + 3) /* Return for quoted string. */ -#define CHAR_ARGV (UCHAR_MAX + 4) /* Return for $@ reference. */ -#define CHAR_RETRY (UCHAR_MAX + 5) /* Return for end of input block. */ - -#define DEF_LQUOTE "`" /* Default left quote delimiter. */ -#define DEF_RQUOTE "\'" /* Default right quote delimiter. */ -#define DEF_BCOMM "#" /* Default begin comment delimiter. */ -#define DEF_ECOMM "\n" /* Default end comment delimiter. */ - -struct m4_syntax_table { - /* Please read the comment at the top of input.c for details. table - holds the current syntax, and orig holds the default syntax. */ - unsigned short table[CHAR_RETRY]; - unsigned short orig[CHAR_RETRY]; - - m4_string_pair quote; /* Quote delimiters. */ - m4_string_pair comm; /* Comment delimiters. */ - - char dollar; /* Dollar character, if is_single_dollar. */ - - /* True iff only one start and end quote delimiter exist. */ - bool_bitfield is_single_quotes : 1; - - /* True iff only one start and end comment delimiter exist. */ - bool_bitfield is_single_comments : 1; - - /* True iff only one byte has M4_SYNTAX_DOLLAR. */ - bool_bitfield is_single_dollar : 1; - - /* True iff some character has M4_SYNTAX_ESCAPE. */ - bool_bitfield is_macro_escaped : 1; - - /* True iff a changesyntax call has impacted something that requires - cleanup at the end. */ - bool_bitfield suspect : 1; - - /* Track the number of changesyntax calls. This saturates at - 0xffff, so the idea is that most users won't be changing the - syntax that frequently; perhaps in the future we will cache - frequently used syntax schemes by index. */ - unsigned short syntax_age; - - /* Track the current quote age, determined by all significant - changequote, changecom, and changesyntax calls, since any of - these can alter the rescan of a prior parameter in a quoted - context. */ - unsigned int quote_age; - - /* Track a cached quote pair on the input obstack. */ - m4_string_pair *cached_quote; - - /* Storage for a simple cached quote that can be recreated on the fly. */ - char cached_lquote[2]; - char cached_rquote[2]; - m4_string_pair cached_simple; -}; - -/* Fast macro versions of syntax table accessor functions, - that also have an identically named function exported in m4module.h. */ -#ifdef NDEBUG -# define m4_get_syntax_lquote(S) ((S)->quote.str1) -# define m4_get_syntax_rquote(S) ((S)->quote.str2) -# define m4_get_syntax_bcomm(S) ((S)->comm.str1) -# define m4_get_syntax_ecomm(S) ((S)->comm.str2) -# define m4_get_syntax_quotes(S) (&(S)->quote) -# define m4_get_syntax_comments(S) (&(S)->comm) - -# define m4_is_syntax_single_quotes(S) ((S)->is_single_quotes) -# define m4_is_syntax_single_comments(S) ((S)->is_single_comments) -# define m4_is_syntax_single_dollar(S) ((S)->is_single_dollar) -# define m4_is_syntax_macro_escaped(S) ((S)->is_macro_escaped) -#endif - -/* Return the current quote age. */ -#define m4__quote_age(S) ((S)->quote_age) - -/* Return true if the current quote age guarantees that parsing the - current token in the context of a quoted string of the same quote - age will give the same parse. */ -#define m4__safe_quotes(S) (((S)->quote_age & 0xffff) != 0) - -/* Set or refresh the cached quote. */ -extern const m4_string_pair *m4__quote_cache (m4_syntax_table *, - m4_obstack *obs, unsigned int, - const m4_string_pair *); - -/* Clear the cached quote. */ -#define m4__quote_uncache(S) ((S)->cached_quote = NULL) - - -/* --- MACRO MANAGEMENT --- */ - -/* Various different token types. */ -typedef enum { - M4_TOKEN_EOF, /* End of file, M4_SYMBOL_VOID. */ - M4_TOKEN_NONE, /* Discardable token, M4_SYMBOL_VOID. */ - M4_TOKEN_STRING, /* Quoted string, M4_SYMBOL_TEXT or M4_SYMBOL_COMP. */ - M4_TOKEN_COMMENT, /* Comment, M4_SYMBOL_TEXT or M4_SYMBOL_COMP. */ - M4_TOKEN_SPACE, /* Whitespace, M4_SYMBOL_TEXT. */ - M4_TOKEN_WORD, /* An identifier, M4_SYMBOL_TEXT. */ - M4_TOKEN_OPEN, /* Argument list start, M4_SYMBOL_TEXT. */ - M4_TOKEN_COMMA, /* Argument separator, M4_SYMBOL_TEXT. */ - M4_TOKEN_CLOSE, /* Argument list end, M4_SYMBOL_TEXT. */ - M4_TOKEN_SIMPLE, /* Single character, M4_SYMBOL_TEXT. */ - M4_TOKEN_MACDEF, /* Builtin token, M4_SYMBOL_FUNC or M4_SYMBOL_COMP. */ - M4_TOKEN_ARGV /* A series of parameters, M4_SYMBOL_COMP. */ -} m4__token_type; - -extern void m4__make_text_link (m4_obstack *, m4__symbol_chain **, - m4__symbol_chain **); -extern void m4__append_builtin (m4_obstack *, const m4__builtin *, - m4__symbol_chain **, - m4__symbol_chain **); -extern bool m4__push_symbol (m4 *, m4_symbol_value *, size_t, - bool); -extern m4_obstack *m4__push_wrapup_init (m4 *, const m4_call_info *, - m4__symbol_chain ***); -extern void m4__push_wrapup_finish (void); -extern m4__token_type m4__next_token (m4 *, m4_symbol_value *, int *, - m4_obstack *, bool, - const m4_call_info *); -extern bool m4__next_token_is_open (m4 *); - -/* Fast macro versions of macro argv accessor functions, - that also have an identically named function exported in m4module.h. */ -#ifdef NDEBUG -# define m4_arg_argc(A) (A)->argc -# define m4_arg_info(A) (A)->info -# define m4_arg_scratch(C) \ - ((C)->arg_stacks[(C)->expansion_level - 1].argv) -#endif /* NDEBUG */ - - -/* --- PATH MANAGEMENT --- */ - -typedef struct m4__search_path m4__search_path; - -struct m4__search_path { - m4__search_path *next; /* next directory to search */ - const char *dir; /* directory */ - int len; -}; - -struct m4__search_path_info { - m4__search_path *list; /* the list of path directories */ - m4__search_path *list_end; /* the end of same */ - int max_length; /* length of longest directory name */ -}; - -extern void m4__include_init (m4 *); - - -/* Debugging the memory allocator. */ - -#if WITH_DMALLOC -# define DMALLOC_FUNC_CHECK -# include -#endif /* WITH_DMALLOC */ - - - -/* Convenience macro to zero a variable after freeing it, as well as - casting away any const. */ -#define DELETE(Expr) ((Expr) = (free ((void *) (Expr)), (void *) 0)) - -/* Avoid negative logic when comparing two strings. */ -#define STREQ(a, b) (strcmp (a, b) == 0) -#define STRNEQ(a, b) (strcmp (a, b) != 0) - - -#if DEBUG -# define DEBUG_INCL 1 -# define DEBUG_INPUT 1 -# define DEBUG_MACRO 1 -# define DEBUG_MODULES 1 -# define DEBUG_OUTPUT 1 -# define DEBUG_STKOVF 1 -# define DEBUG_SYM 1 -# define DEBUG_SYNTAX 1 -#endif - -#endif /* m4private.h */ diff --git a/m4/macro.c b/m4/macro.c deleted file mode 100644 index ce2675b2..00000000 --- a/m4/macro.c +++ /dev/null @@ -1,1784 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 2001, 2006-2010, 2013-2014, 2017 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 . -*/ - -/* This file contains the functions that perform the basic argument - parsing and macro expansion. */ - -#include - -#include "m4private.h" - -/* Define this to 1 see runtime debug info. Implied by DEBUG. */ -/*#define DEBUG_INPUT 1 */ -#ifndef DEBUG_MACRO -# define DEBUG_MACRO 0 -#endif /* DEBUG_MACRO */ - -/* A note on argument memory lifetimes: We use an internal struct - (m4__macro_args_stacks) to maintain list of argument obstacks. - Within a recursion level, consecutive macros can share a stack, but - distinct recursion levels need different stacks since the nested - macro is interrupting the argument collection of the outer level. - Note that a reference can live as long as the expansion containing - the reference can participate as an argument in a future macro - call. - - Therefore, we implement a reference counter for each expansion - level, tracking how many references exist into the obstack, as well - as associate a level with each reference. Of course, expand_macro - is actively using argv, so it increments the refcount on entry and - decrements it on exit. Additionally, any time the input engine is - handed a reference that it does not inline, it increases the - refcount in push_token, then decreases it in pop_input once the - reference has been rescanned. Finally, when the input engine hands - a reference back to expand_argument, the refcount increases, which - is then cleaned up at the end of expand_macro. - - For a running example, consider this input: - - define(a,A)define(b,`a(`$1')')define(c,$*)dnl - define(x,`a(1)`'c($@')define(y,`$@)')dnl - x(a(`b')``a'')y(`b')(`a') - => AAaA - - Assuming all arguments are large enough to exceed the inlining - thresholds of the input engine, the interesting sequence of events - is as follows: - - stacks[0] refs stacks[1] refs - after second dnl ends: `' 0 `' 0 - expand_macro for x, level 0: `' 1 `' 0 - expand_macro for a, level 1: `' 1 `' 1 - after collect_arguments for a: `' 1 `b' 1 - push `A' to input stack: `' 1 `b' 1 - exit expand_macro for a: `' 1 `' 0 - after collect_arguments for x: `A`a'' 1 `' 0 - push `a(1)`'c(' to input stack: `A`a'' 1 `' 0 - push_token saves $@(x) ref: `A`a'' 2 `' 0 - exit expand_macro for x: `A`a'' 1 `' 0 - expand_macro for a, level 0: `A`a'' 2 `' 0 - after collect_arguments for a: `A`a''`1' 2 `' 0 - push `A' to input stack: `A`a''`1' 2 `' 0 - exit expand_macro for a: `A`a'' 1 `' 0 - output `A': `A`a'' 1 `' 0 - expand_macro for c, level 0: `A`a'' 2 `' 0 - expand_argument gets $@(x) ref: `A`a''`$@(x)' 3 `' 0 - pop_input ends $@(x) ref: `A`a''`$@(x)' 2 `' 0 - expand_macro for y, level 1: `A`a''`$@(x)' 2 `' 1 - after collect_arguments for y: `A`a''`$@(x)' 2 `b' 1 - push_token saves $@(y) ref: `A`a''`$@(x)' 2 `b' 2 - push `)' to input stack: `A`a''`$@(x)' 2 `b' 2 - exit expand_macro for y: `A`a''`$@(x)' 2 `b' 1 - expand_argument gets $@(y) ref: `A`a''`$@(x)$@(y)' 2 `b' 2 - pop_input ends $@(y) ref: `A`a''`$@(x)$@(y)' 2 `b' 1 - after collect_arguments for c: `A`a''`$@(x)$@(y)' 2 `b' 1 - push_token saves $*(c) ref: `A`a''`$@(x)$@(y)' 3 `b' 2 - expand_macro frees $@(x) ref: `A`a''`$@(x)$@(y)' 2 `b' 2 - expand_macro frees $@(y) ref: `A`a''`$@(x)$@(y)' 2 `b' 1 - exit expand_macro for c: `A`a''`$@(x)$@(y)' 1 `b' 1 - output `Aa': `A`a''`$@(x)$@(y)' 0 `b' 1 - pop_input ends $*(c)$@(x) ref: `' 0 `b' 1 - expand_macro for b, level 0: `' 1 `b' 1 - pop_input ends $*(c)$@(y) ref: `' 1 `' 0 - after collect_arguments for b: `a' 1 `' 0 - push `a(`' to input stack: `a' 1 `' 0 - push_token saves $1(b) ref: `a' 2 `' 0 - push `')' to input stack: `a' 2 `' 0 - exit expand_macro for b: `a' 1 `' 0 - expand_macro for a, level 0 : `a' 2 `' 0 - expand_argument gets $1(b) ref: `a'`$1(b)' 3 `' 0 - pop_input ends $1(b) ref: `a'`$1(b)' 2 `' 0 - after collect_arguments for a: `a'`$1(b)' 2 `' 0 - push `A' to input stack: `a'`$1(b)' 2 `' 0 - expand_macro frees $1(b) ref: `a'`$1(b)' 1 `' 0 - exit expand_macro for a: `' 0 `' 0 - output `A': `' 0 `' 0 - - An obstack is only completely cleared when its refcount reaches - zero. However, as an optimization, expand_macro also frees - anything that it added to the obstack if no additional references - were added at the current expansion level, to reduce the amount of - memory left on the obstack while waiting for refcounts to drop. -*/ - -static m4_macro_args *collect_arguments (m4 *, m4_call_info *, m4_symbol *, - m4_obstack *, m4_obstack *); -static void expand_macro (m4 *, const char *, size_t, m4_symbol *); -static bool expand_token (m4 *, m4_obstack *, m4__token_type, - m4_symbol_value *, int, bool); -static bool expand_argument (m4 *, m4_obstack *, m4_symbol_value *, - const m4_call_info *); -static void process_macro (m4 *, m4_symbol_value *, m4_obstack *, int, - m4_macro_args *); - -static unsigned int trace_pre (m4 *, m4_macro_args *); -static void trace_post (m4 *, unsigned int, const m4_call_info *); -static unsigned int trace_header (m4 *, const m4_call_info *); -static void trace_flush (m4 *, unsigned int); - - -/* The number of the current call of expand_macro (). */ -static size_t macro_call_id = 0; - -/* A placeholder symbol value representing the empty string, used to - optimize checks for emptiness. */ -static m4_symbol_value empty_symbol; - -#if DEBUG_MACRO -/* True if significant changes to stacks should be printed to the - trace stream. Primarily useful for debugging $@ ref memory leaks, - and controlled by M4_DEBUG_MACRO environment variable. */ -static int debug_macro_level; -#else -# define debug_macro_level 0 -#endif /* !DEBUG_MACRO */ -#define PRINT_ARGCOUNT_CHANGES 1 /* Any change to argcount > 1. */ -#define PRINT_REFCOUNT_INCREASE 2 /* Any increase to refcount. */ -#define PRINT_REFCOUNT_DECREASE 4 /* Any decrease to refcount. */ - - - -/* This function reads all input, and expands each token, one at a time. */ -void -m4_macro_expand_input (m4 *context) -{ - m4__token_type type; - m4_symbol_value token; - int line; - -#if DEBUG_MACRO - const char *s = getenv ("M4_DEBUG_MACRO"); - if (s) - debug_macro_level = strtol (s, NULL, 0); -#endif /* DEBUG_MACRO */ - - m4_set_symbol_value_text (&empty_symbol, "", 0, 0); - VALUE_MAX_ARGS (&empty_symbol) = -1; - - while ((type = m4__next_token (context, &token, &line, NULL, false, NULL)) - != M4_TOKEN_EOF) - expand_token (context, NULL, type, &token, line, true); -} - - -/* Expand one token onto OBS, according to its type. If OBS is NULL, - output the expansion to the current diversion. TYPE determines the - contents of TOKEN. Potential macro names (a TYPE of M4_TOKEN_WORD) - are looked up in the symbol table, to see if they have a macro - definition. If they have, they are expanded as macros, otherwise - the text are just copied to the output. LINE determines where - TOKEN began. FIRST is true if there is no prior content in the - current macro argument. Return true if the result is guranteed to - give the same parse on rescan in a quoted context with the same - quote age. Returning false is always safe, although it may lead to - slower performance. */ -static bool -expand_token (m4 *context, m4_obstack *obs, m4__token_type type, - m4_symbol_value *token, int line, bool first) -{ - m4_symbol *symbol; - bool result = false; - const char *text = (m4_is_symbol_value_text (token) - ? m4_get_symbol_value_text (token) : NULL); - - switch (type) - { /* TOKSW */ - case M4_TOKEN_EOF: - case M4_TOKEN_MACDEF: - /* Always safe, since there is no text to rescan. */ - return true; - - case M4_TOKEN_STRING: - /* Strings are safe in isolation (since quote_age detects any - change in delimiters), or when safe_quotes is true. This is - also returned for sequences of benign characters, such as - digits. When safe_quotes is false, we could technically - return true if we can prove that the concatenation of this - string to prior text does not form a multi-byte quote - delimiter, but that is a lot of overhead, so we give the - conservative answer of false. */ - result = first || m4__safe_quotes (M4SYNTAX); - /* fallthru */ - case M4_TOKEN_COMMENT: - /* Comments can contain unbalanced quote delimiters. Rather - than search for one, we return the conservative answer of - false. If obstack is provided, the string or comment was - already expanded into it during next_token. */ - if (obs) - return result; - break; - - case M4_TOKEN_OPEN: - case M4_TOKEN_COMMA: - case M4_TOKEN_CLOSE: - case M4_TOKEN_SPACE: - /* If safe_quotes is true, then these do not form a quote - delimiter. If it is false, we give the conservative answer - of false rather than taking time to prove that no multi-byte - quote delimiter is formed. */ - result = m4__safe_quotes (M4SYNTAX); - break; - - case M4_TOKEN_SIMPLE: - /* If safe_quotes is true, then all but the single-byte end - quote delimiter is safe in a quoted context; a single-byte - start delimiter will trigger M4_TOKEN_STRING instead. If - safe_quotes is false, we give the conservative answer of - false rather than taking time to prove that no multi-byte - quote delimiter is formed. */ - result = (!m4_has_syntax (M4SYNTAX, *text, M4_SYNTAX_RQUOTE) - && m4__safe_quotes (M4SYNTAX)); - if (result) - assert (!m4_has_syntax (M4SYNTAX, *text, M4_SYNTAX_LQUOTE)); - break; - - case M4_TOKEN_WORD: - { - const char *textp = text; - size_t len = m4_get_symbol_value_len (token); - size_t len2 = len; - - if (m4_has_syntax (M4SYNTAX, *textp, M4_SYNTAX_ESCAPE)) - { - textp++; - len2--; - } - - symbol = m4_symbol_lookup (M4SYMTAB, textp, len2); - assert (!symbol || !m4_is_symbol_void (symbol)); - if (symbol == NULL - || (symbol->value->type == M4_SYMBOL_FUNC - && BIT_TEST (SYMBOL_FLAGS (symbol), VALUE_BLIND_ARGS_BIT) - && !m4__next_token_is_open (context))) - { - m4_divert_text (context, obs, text, len, line); - /* If safe_quotes is true, then words do not overlap with - quote delimiters. If it is false, we give the - conservative answer of false rather than prove that no - multi-byte delimiters are formed. */ - return m4__safe_quotes (M4SYNTAX); - } - expand_macro (context, textp, len2, symbol); - /* Expanding a macro may create new tokens to scan, and those - tokens may generate unsafe text, but we did not append any - text now. */ - return true; - } - - default: - assert (!"INTERNAL ERROR: bad token type in expand_token ()"); - abort (); - } - m4_divert_text (context, obs, text, m4_get_symbol_value_len (token), line); - return result; -} - - -/* This function parses one argument to a macro call. It expects the - first left parenthesis or the separating comma to have been read by - the caller. It skips leading whitespace, then reads and expands - tokens, until it finds a comma or a right parenthesis at the same - level of parentheses. It returns a flag indicating whether the - argument read is the last for the active macro call. The arguments - are built on the obstack OBS, indirectly through expand_token (). - Report errors on behalf of CALLER. */ -static bool -expand_argument (m4 *context, m4_obstack *obs, m4_symbol_value *argp, - const m4_call_info *caller) -{ - m4__token_type type; - m4_symbol_value token; - int paren_level = 0; - int line = m4_get_current_line (context); - size_t len; - unsigned int age = m4__quote_age (M4SYNTAX); - bool first = true; - - memset (argp, '\0', sizeof *argp); - VALUE_MAX_ARGS (argp) = -1; - - /* Skip leading white space. */ - do - { - type = m4__next_token (context, &token, NULL, obs, true, caller); - } - while (type == M4_TOKEN_SPACE); - - while (1) - { - if (VALUE_MIN_ARGS (argp) < VALUE_MIN_ARGS (&token)) - VALUE_MIN_ARGS (argp) = VALUE_MIN_ARGS (&token); - if (VALUE_MAX_ARGS (&token) < VALUE_MAX_ARGS (argp)) - VALUE_MAX_ARGS (argp) = VALUE_MAX_ARGS (&token); - switch (type) - { /* TOKSW */ - case M4_TOKEN_COMMA: - case M4_TOKEN_CLOSE: - if (paren_level == 0) - { - assert (argp->type != M4_SYMBOL_FUNC); - if (argp->type != M4_SYMBOL_COMP) - { - len = obstack_object_size (obs); - VALUE_MODULE (argp) = NULL; - if (len) - { - obstack_1grow (obs, '\0'); - m4_set_symbol_value_text (argp, obstack_finish (obs), - len, age); - } - else - m4_set_symbol_value_text (argp, "", len, 0); - } - else - { - m4__make_text_link (obs, NULL, &argp->u.u_c.end); - if (argp->u.u_c.chain == argp->u.u_c.end - && argp->u.u_c.chain->type == M4__CHAIN_FUNC) - { - const m4__builtin *func = argp->u.u_c.chain->u.builtin; - argp->type = M4_SYMBOL_FUNC; - argp->u.builtin = func; - } - } - return type == M4_TOKEN_COMMA; - } - /* fallthru */ - case M4_TOKEN_OPEN: - case M4_TOKEN_SIMPLE: - if (type == M4_TOKEN_OPEN) - paren_level++; - else if (type == M4_TOKEN_CLOSE) - paren_level--; - if (!expand_token (context, obs, type, &token, line, first)) - age = 0; - break; - - case M4_TOKEN_EOF: - m4_error (context, EXIT_FAILURE, 0, caller, - _("end of file in argument list")); - break; - - case M4_TOKEN_WORD: - case M4_TOKEN_SPACE: - case M4_TOKEN_STRING: - case M4_TOKEN_COMMENT: - case M4_TOKEN_MACDEF: - if (!expand_token (context, obs, type, &token, line, first)) - age = 0; - if (token.type == M4_SYMBOL_COMP) - { - if (argp->type != M4_SYMBOL_COMP) - { - argp->type = M4_SYMBOL_COMP; - argp->u.u_c.chain = token.u.u_c.chain; - argp->u.u_c.wrapper = argp->u.u_c.has_func = false; - } - else - { - assert (argp->u.u_c.end); - argp->u.u_c.end->next = token.u.u_c.chain; - } - argp->u.u_c.end = token.u.u_c.end; - if (token.u.u_c.has_func) - argp->u.u_c.has_func = true; - } - break; - - case M4_TOKEN_ARGV: - assert (paren_level == 0 && argp->type == M4_SYMBOL_VOID - && obstack_object_size (obs) == 0 - && token.u.u_c.chain == token.u.u_c.end - && token.u.u_c.chain->quote_age == age - && token.u.u_c.chain->type == M4__CHAIN_ARGV); - argp->type = M4_SYMBOL_COMP; - argp->u.u_c.chain = argp->u.u_c.end = token.u.u_c.chain; - argp->u.u_c.wrapper = true; - argp->u.u_c.has_func = token.u.u_c.has_func; - type = m4__next_token (context, &token, NULL, NULL, false, caller); - if (argp->u.u_c.chain->u.u_a.skip_last) - assert (type == M4_TOKEN_COMMA); - else - assert (type == M4_TOKEN_COMMA || type == M4_TOKEN_CLOSE); - return type == M4_TOKEN_COMMA; - - default: - assert (!"expand_argument"); - abort (); - } - - if (argp->type != M4_SYMBOL_VOID || obstack_object_size (obs)) - first = false; - type = m4__next_token (context, &token, NULL, obs, first, caller); - } -} - - -/* The macro expansion is handled by expand_macro (). It parses the - arguments, using collect_arguments (), and builds a table of pointers to - the arguments. The arguments themselves are stored on a local obstack. - Expand_macro () uses m4_macro_call () to do the call of the macro. - - Expand_macro () is potentially recursive, since it calls expand_argument - (), which might call expand_token (), which might call expand_macro (). - - NAME points to storage on the token stack, so it is only valid - until a call to collect_arguments parses more tokens. SYMBOL is - the result of the symbol table lookup on NAME. */ -static void -expand_macro (m4 *context, const char *name, size_t len, m4_symbol *symbol) -{ - void *args_base; /* Base of stack->args on entry. */ - void *args_scratch; /* Base of scratch space for m4_macro_call. */ - void *argv_base; /* Base of stack->argv on entry. */ - m4_macro_args *argv; /* Arguments to the called macro. */ - m4_obstack *expansion; /* Collects the macro's expansion. */ - m4_symbol_value *value; /* Original value of this macro. */ - size_t level; /* Expansion level of this macro. */ - m4__macro_arg_stacks *stack; /* Storage for this macro. */ - m4_call_info info; /* Context of this macro call. */ - - /* Obstack preparation. */ - level = context->expansion_level; - if (context->stacks_count <= level) - { - size_t count = context->stacks_count; - context->arg_stacks - = (m4__macro_arg_stacks *) x2nrealloc (context->arg_stacks, - &context->stacks_count, - sizeof *context->arg_stacks); - memset (&context->arg_stacks[count], 0, - sizeof *context->arg_stacks * (context->stacks_count - count)); - } - stack = &context->arg_stacks[level]; - if (!stack->args) - { - assert (!stack->refcount); - stack->args = (m4_obstack *) xmalloc (sizeof *stack->args); - stack->argv = (m4_obstack *) xmalloc (sizeof *stack->argv); - obstack_init (stack->args); - obstack_init (stack->argv); - stack->args_base = obstack_finish (stack->args); - stack->argv_base = obstack_finish (stack->argv); - } - assert (obstack_object_size (stack->args) == 0 - && obstack_object_size (stack->argv) == 0); - args_base = obstack_finish (stack->args); - argv_base = obstack_finish (stack->argv); - m4__adjust_refcount (context, level, true); - stack->argcount++; - - /* Grab the current value of this macro, because it may change while - collecting arguments. Likewise, grab any state needed during - tracing. */ - value = m4_get_symbol_value (symbol); - info.file = m4_get_current_file (context); - info.line = m4_get_current_line (context); - info.call_id = ++macro_call_id; - info.trace = (m4_is_debug_bit (context, M4_DEBUG_TRACE_ALL) - || m4_get_symbol_traced (symbol)); - info.debug_level = m4_get_debug_level_opt (context); - info.name = name; - info.name_len = len; - - /* Prepare for macro expansion. */ - VALUE_PENDING (value)++; - if (m4_get_nesting_limit_opt (context) < ++context->expansion_level) - m4_error (context, EXIT_FAILURE, 0, NULL, _("\ -recursion limit of %zu exceeded, use -L to change it"), - m4_get_nesting_limit_opt (context)); - - m4_trace_prepare (context, &info, value); - argv = collect_arguments (context, &info, symbol, stack->args, stack->argv); - /* Since collect_arguments can invalidate stack by reallocating - context->arg_stacks during a recursive expand_macro call, we must - reset it here. */ - stack = &context->arg_stacks[level]; - args_scratch = obstack_finish (stack->args); - - /* The actual macro call. */ - expansion = m4_push_string_init (context, info.file, info.line); - m4_macro_call (context, value, expansion, argv); - m4_push_string_finish (); - - /* Cleanup. */ - argv->info = NULL; - - --context->expansion_level; - --VALUE_PENDING (value); - if (BIT_TEST (VALUE_FLAGS (value), VALUE_DELETED_BIT)) - m4_symbol_value_delete (value); - - /* We no longer need argv, so reduce the refcount. Additionally, if - no other references to argv were created, we can free our portion - of the obstack, although we must leave earlier content alone. A - refcount of 0 implies that adjust_refcount already freed the - entire stack. */ - m4__arg_adjust_refcount (context, argv, false); - if (stack->refcount) - { - if (argv->inuse) - { - obstack_free (stack->args, args_scratch); - if (debug_macro_level & PRINT_ARGCOUNT_CHANGES) - xfprintf (stderr, "m4debug: -%zu- `%s' in use, level=%zu, " - "refcount=%zu, argcount=%zu\n", info.call_id, - argv->info->name, level, stack->refcount, - stack->argcount); - } - else - { - obstack_free (stack->args, args_base); - obstack_free (stack->argv, argv_base); - stack->argcount--; - } - } -} - -/* Collect all the arguments to a call of the macro SYMBOL, with call - context INFO. The arguments are stored on the obstack ARGUMENTS - and a table of pointers to the arguments on ARGV_STACK. Return the - object describing all of the macro arguments. */ -static m4_macro_args * -collect_arguments (m4 *context, m4_call_info *info, m4_symbol *symbol, - m4_obstack *arguments, m4_obstack *argv_stack) -{ - m4_symbol_value token; - m4_symbol_value *tokenp; - bool more_args; - m4_macro_args args; - m4_macro_args *argv; - - args.argc = 1; - args.inuse = false; - args.wrapper = false; - args.has_ref = false; - args.flatten = m4_symbol_flatten_args (symbol); - args.has_func = false; - /* Must copy here, since we are consuming tokens, and since symbol - table can be changed during argument collection. */ - info->name = (char *) obstack_copy0 (arguments, info->name, info->name_len); - args.quote_age = m4__quote_age (M4SYNTAX); - args.info = info; - args.level = context->expansion_level - 1; - args.arraylen = 0; - obstack_grow (argv_stack, &args, offsetof (m4_macro_args, array)); - - if (m4__next_token_is_open (context)) - { - /* Gobble parenthesis, then collect arguments. */ - m4__next_token (context, &token, NULL, NULL, false, info); - do - { - tokenp = (m4_symbol_value *) obstack_alloc (arguments, - sizeof *tokenp); - more_args = expand_argument (context, arguments, tokenp, info); - - if ((m4_is_symbol_value_text (tokenp) - && !m4_get_symbol_value_len (tokenp)) - || (args.flatten && m4_is_symbol_value_func (tokenp))) - { - obstack_free (arguments, tokenp); - tokenp = &empty_symbol; - } - obstack_ptr_grow (argv_stack, tokenp); - args.arraylen++; - args.argc++; - switch (tokenp->type) - { - case M4_SYMBOL_TEXT: - /* Be conservative - any change in quoting while - collecting arguments, or any unsafe argument, will - require a rescan if $@ is reused. */ - if (m4_get_symbol_value_len (tokenp) - && m4_get_symbol_value_quote_age (tokenp) != args.quote_age) - args.quote_age = 0; - break; - case M4_SYMBOL_FUNC: - args.has_func = true; - break; - case M4_SYMBOL_COMP: - args.has_ref = true; - if (tokenp->u.u_c.wrapper) - { - assert (tokenp->u.u_c.chain->type == M4__CHAIN_ARGV - && !tokenp->u.u_c.chain->next); - args.argc += (tokenp->u.u_c.chain->u.u_a.argv->argc - - tokenp->u.u_c.chain->u.u_a.index - - tokenp->u.u_c.chain->u.u_a.skip_last - 1); - args.wrapper = true; - } - if (tokenp->u.u_c.has_func) - args.has_func = true; - break; - default: - assert (!"expand_argument"); - abort (); - } - } - while (more_args); - } - argv = (m4_macro_args *) obstack_finish (argv_stack); - argv->argc = args.argc; - argv->wrapper = args.wrapper; - argv->has_ref = args.has_ref; - argv->has_func = args.has_func; - if (args.quote_age != m4__quote_age (M4SYNTAX)) - argv->quote_age = 0; - argv->arraylen = args.arraylen; - return argv; -} - - -/* The actual call of a macro is handled by m4_macro_call (). - m4_macro_call () is passed a symbol VALUE, whose type is used to - call either a builtin function, or the user macro expansion - function process_macro (). The arguments are provided by the ARGV - table. The expansion is left on the obstack EXPANSION. Macro - tracing is also handled here. */ -void -m4_macro_call (m4 *context, m4_symbol_value *value, m4_obstack *expansion, - m4_macro_args *argv) -{ - unsigned int trace_start = 0; - - if (argv->info->trace) - trace_start = trace_pre (context, argv); - if (!m4_bad_argc (context, argv->argc, argv->info, - VALUE_MIN_ARGS (value), VALUE_MAX_ARGS (value), - BIT_TEST (VALUE_FLAGS (value), - VALUE_SIDE_EFFECT_ARGS_BIT))) - { - if (m4_is_symbol_value_text (value)) - process_macro (context, value, expansion, argv->argc, argv); - else if (m4_is_symbol_value_func (value)) - m4_get_symbol_value_func (value) (context, expansion, argv->argc, - argv); - else if (m4_is_symbol_value_placeholder (value)) - m4_warn (context, 0, argv->info, - _("builtin %s requested by frozen file not found"), - quotearg_style (locale_quoting_style, - m4_get_symbol_value_placeholder (value))); - else - { - assert (!"m4_macro_call"); - abort (); - } - } - if (argv->info->trace) - trace_post (context, trace_start, argv->info); -} - -/* This function handles all expansion of user defined and predefined - macros. It is called with an obstack OBS, where the macros expansion - will be placed, as an unfinished object. SYMBOL points to the macro - definition, giving the expansion text. ARGC and ARGV are the arguments, - as usual. */ -static void -process_macro (m4 *context, m4_symbol_value *value, m4_obstack *obs, - int argc, m4_macro_args *argv) -{ - const char *text = m4_get_symbol_value_text (value); - size_t len = m4_get_symbol_value_len (value); - const char *end = text + len; - int i; - while (1) - { - const char *dollar; - if (m4_is_syntax_single_dollar (M4SYNTAX)) - dollar = (char *) memchr (text, M4SYNTAX->dollar, len); - else - { - dollar = text; - while (dollar != end) - { - if (m4_has_syntax (M4SYNTAX, *dollar, M4_SYNTAX_DOLLAR)) - break; - dollar++; - } - if (dollar == end) - dollar = NULL; - } - if (!dollar) - { - obstack_grow (obs, text, len); - return; - } - obstack_grow (obs, text, dollar - text); - len -= dollar - text; - text = dollar; - if (len == 1) - { - obstack_1grow (obs, *dollar); - return; - } - len--; - switch (*++text) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - /* FIXME - multidigit arguments should convert over to ${10} - syntax instead of $10; see - http://lists.gnu.org/archive/html/m4-discuss/2006-08/msg00028.html - for more discussion. */ - if (m4_get_posixly_correct_opt (context) - || !isdigit (to_uchar (text[1]))) - { - i = *text++ - '0'; - len--; - } - else - { - char *endp; - i = (int) strtol (text, &endp, 10); - len -= endp - text; - text = endp; - } - if (i < argc) - m4_push_arg (context, obs, argv, i); - break; - - case '#': /* number of arguments */ - m4_shipout_int (obs, argc - 1); - text++; - len--; - break; - - case '*': /* all arguments */ - case '@': /* ... same, but quoted */ - m4_push_args (context, obs, argv, false, *text == '@'); - text++; - len--; - break; - - default: - if (m4_get_posixly_correct_opt (context) - || !VALUE_ARG_SIGNATURE (value)) - { - obstack_1grow (obs, *dollar); - } - else - { - size_t len1 = 0; - const char *endp; - char *key; - - for (endp = ++text; - len1 < len && m4_has_syntax (M4SYNTAX, *endp, - (M4_SYNTAX_OTHER - | M4_SYNTAX_ALPHA - | M4_SYNTAX_NUM)); - ++endp) - { - ++len1; - } - key = xstrndup (text, len1); - - if (*endp) - { - struct m4_symbol_arg **arg - = (struct m4_symbol_arg **) - m4_hash_lookup (VALUE_ARG_SIGNATURE (value), key); - - if (arg) - { - i = SYMBOL_ARG_INDEX (*arg); - assert (i < argc); - m4_shipout_string (context, obs, M4ARG (i), M4ARGLEN (i), - false); - } - } - else - { - m4_error (context, 0, 0, argv->info, - _("unterminated parameter reference: %s"), key); - } - - len -= endp - text; - text = endp; - - free (key); - } - break; - } - } -} - - - -/* The next portion of this file contains the functions for macro - tracing output. All tracing output for a macro call is collected - on an obstack TRACE, and printed whenever the line is complete. - This prevents tracing output from interfering with other debug - messages generated by the various builtins. */ - -/* Format the standard header attached to all tracing output lines, - using the context in INFO as appropriate. Return the offset into - the trace obstack where this particular trace begins. */ -static unsigned int -trace_header (m4 *context, const m4_call_info *info) -{ - m4_obstack *trace = &context->trace_messages; - unsigned int result = obstack_object_size (trace); - obstack_grow (trace, "m4trace:", 8); - if (info->debug_level & M4_DEBUG_TRACE_FILE) - obstack_printf (trace, "%s:", info->file); - if (info->debug_level & M4_DEBUG_TRACE_LINE) - obstack_printf (trace, "%d:", info->line); - obstack_printf (trace, " -%zu- ", context->expansion_level); - if (info->debug_level & M4_DEBUG_TRACE_CALLID) - obstack_printf (trace, "id %zu: ", info->call_id); - return result; -} - -/* Print current tracing line starting at offset START, as returned - from an earlier trace_header(), then clear the obstack. */ -static void -trace_flush (m4 *context, unsigned int start) -{ - char *str; - size_t len = obstack_object_size (&context->trace_messages); - FILE *file = m4_get_debug_file (context); - - if (file) - { - /* TODO - quote nonprintable characters if debug is tty? */ - str = (char *) obstack_base (&context->trace_messages); - fwrite (&str[start], 1, len - start, file); - fputc ('\n', file); - } - obstack_blank_fast (&context->trace_messages, start - len); -} - -/* Do pre-argument-collection tracing for the macro described in INFO. - Should be called prior to m4_macro_call(). */ -void -m4_trace_prepare (m4 *context, const m4_call_info *info, - m4_symbol_value *value) -{ - const m4_string_pair *quotes = NULL; - size_t arg_length = m4_get_max_debug_arg_length_opt (context); - bool module = (info->debug_level & M4_DEBUG_TRACE_MODULE) != 0; - - if (info->debug_level & M4_DEBUG_TRACE_QUOTE) - quotes = m4_get_syntax_quotes (M4SYNTAX); - if (info->trace && (info->debug_level & M4_DEBUG_TRACE_CALL)) - { - unsigned int start = trace_header (context, info); - obstack_grow (&context->trace_messages, info->name, info->name_len); - obstack_grow (&context->trace_messages, " ... = ", 7); - m4__symbol_value_print (context, value, &context->trace_messages, quotes, - false, NULL, &arg_length, module); - trace_flush (context, start); - } -} - -/* Format the parts of a trace line that are known via ARGV before the - macro is actually expanded. Used from m4_macro_call(). Return the - start of the current trace, in case other traces are printed before - this trace completes trace_post. */ -static unsigned int -trace_pre (m4 *context, m4_macro_args *argv) -{ - int trace_level = argv->info->debug_level; - unsigned int start = trace_header (context, argv->info); - m4_obstack *trace = &context->trace_messages; - - assert (argv->info->trace); - obstack_grow (trace, argv->info->name, argv->info->name_len); - - if (1 < m4_arg_argc (argv) && (trace_level & M4_DEBUG_TRACE_ARGS)) - { - const m4_string_pair *quotes = NULL; - size_t arg_length = m4_get_max_debug_arg_length_opt (context); - bool module = (trace_level & M4_DEBUG_TRACE_MODULE) != 0; - - if (trace_level & M4_DEBUG_TRACE_QUOTE) - quotes = m4_get_syntax_quotes (M4SYNTAX); - obstack_1grow (trace, '('); - m4__arg_print (context, trace, argv, 1, quotes, false, NULL, ", ", - &arg_length, true, module); - obstack_1grow (trace, ')'); - } - return start; -} - -/* If requested by the trace state in INFO, format the final part of a - trace line. Then print all collected information from START, - returned from a prior trace_pre(). Used from m4_macro_call (). */ -static void -trace_post (m4 *context, unsigned int start, const m4_call_info *info) -{ - assert (info->trace); - if (info->debug_level & M4_DEBUG_TRACE_EXPANSION) - { - obstack_grow (&context->trace_messages, " -> ", 4); - m4_input_print (context, &context->trace_messages, info->debug_level); - } - trace_flush (context, start); -} - - -/* Accessors into m4_macro_args. */ - -/* Adjust the refcount of argument stack LEVEL. If INCREASE, then - increase the count, otherwise decrease the count and clear the - entire stack if the new count is zero. Return the new - refcount. */ -size_t -m4__adjust_refcount (m4 *context, size_t level, bool increase) -{ - m4__macro_arg_stacks *stack = &context->arg_stacks[level]; - assert (level < context->stacks_count && stack->args - && (increase || stack->refcount)); - if (increase) - stack->refcount++; - else if (--stack->refcount == 0) - { - obstack_free (stack->args, stack->args_base); - obstack_free (stack->argv, stack->argv_base); - if ((debug_macro_level & PRINT_ARGCOUNT_CHANGES) && 1 < stack->argcount) - xfprintf (stderr, "m4debug: -%zu- freeing %zu args, level=%zu\n", - macro_call_id, stack->argcount, level); - stack->argcount = 0; - } - if (debug_macro_level - & (increase ? PRINT_REFCOUNT_INCREASE : PRINT_REFCOUNT_DECREASE)) - xfprintf (stderr, "m4debug: level %zu refcount=%zu\n", level, - stack->refcount); - return stack->refcount; -} - -/* Given ARGV, adjust the refcount of every reference it contains in - the direction decided by INCREASE. Return true if increasing - references to ARGV implies the first use of ARGV. */ -bool -m4__arg_adjust_refcount (m4 *context, m4_macro_args *argv, bool increase) -{ - size_t i; - m4__symbol_chain *chain; - bool result = !argv->inuse; - - if (argv->has_ref) - for (i = 0; i < argv->arraylen; i++) - if (argv->array[i]->type == M4_SYMBOL_COMP) - { - chain = argv->array[i]->u.u_c.chain; - while (chain) - { - switch (chain->type) - { - case M4__CHAIN_STR: - if (chain->u.u_s.level < SIZE_MAX) - m4__adjust_refcount (context, chain->u.u_s.level, - increase); - break; - case M4__CHAIN_FUNC: - break; - case M4__CHAIN_ARGV: - assert (chain->u.u_a.argv->inuse); - m4__arg_adjust_refcount (context, chain->u.u_a.argv, - increase); - break; - default: - assert (!"m4__arg_adjust_refcount"); - abort (); - } - chain = chain->next; - } - } - m4__adjust_refcount (context, argv->level, increase); - return result; -} - -/* Mark ARGV as being in use, along with any $@ references that it - wraps. */ -static void -arg_mark (m4_macro_args *argv) -{ - size_t i; - m4__symbol_chain *chain; - - if (argv->inuse) - return; - argv->inuse = true; - if (argv->wrapper) - { - for (i = 0; i < argv->arraylen; i++) - if (argv->array[i]->type == M4_SYMBOL_COMP - && argv->array[i]->u.u_c.wrapper) - { - chain = argv->array[i]->u.u_c.chain; - assert (!chain->next && chain->type == M4__CHAIN_ARGV); - if (!chain->u.u_a.argv->inuse) - arg_mark (chain->u.u_a.argv); - } - } -} - -/* Populate the newly-allocated VALUE as a wrapper around ARGV, - starting with argument ARG. Allocate any data on OBS, owned by a - given expansion LEVEL. FLATTEN determines whether to allow - builtins, and QUOTES determines whether all arguments are quoted. - Return TOKEN when successful, NULL when wrapping ARGV is trivially - empty. */ -static m4_symbol_value * -make_argv_ref (m4 *context, m4_symbol_value *value, m4_obstack *obs, - size_t level, m4_macro_args *argv, size_t arg, bool flatten, - const m4_string_pair *quotes) -{ - m4__symbol_chain *chain; - - if (argv->argc <= arg) - return NULL; - value->type = M4_SYMBOL_COMP; - value->u.u_c.chain = value->u.u_c.end = NULL; - - /* Cater to the common idiom of $0(`$1',shift(shift($@))), by - inlining the first few arguments and reusing the original $@ ref, - rather than creating another layer of wrappers. */ - while (argv->wrapper) - { - size_t i; - for (i = 0; i < argv->arraylen; i++) - { - if ((argv->array[i]->type == M4_SYMBOL_COMP - && argv->array[i]->u.u_c.wrapper) - || level < SIZE_MAX) - break; - if (arg == 1) - { - m4__push_arg_quote (context, obs, argv, i + 1, quotes); - /* TODO support M4_SYNTAX_COMMA. */ - obstack_1grow (obs, ','); - } - else - arg--; - } - assert (i < argv->arraylen); - if (i + 1 == argv->arraylen) - { - assert (argv->array[i]->type == M4_SYMBOL_COMP - && argv->array[i]->u.u_c.wrapper); - chain = argv->array[i]->u.u_c.chain; - assert (!chain->next && chain->type == M4__CHAIN_ARGV - && !chain->u.u_a.skip_last); - argv = chain->u.u_a.argv; - arg += chain->u.u_a.index - 1; - } - else - { - arg += i; - break; - } - } - - m4__make_text_link (obs, &value->u.u_c.chain, &value->u.u_c.end); - chain = (m4__symbol_chain *) obstack_alloc (obs, sizeof *chain); - if (value->u.u_c.end) - value->u.u_c.end->next = chain; - else - value->u.u_c.chain = chain; - value->u.u_c.end = chain; - value->u.u_c.wrapper = true; - value->u.u_c.has_func = argv->has_func; - chain->next = NULL; - chain->type = M4__CHAIN_ARGV; - chain->quote_age = argv->quote_age; - chain->u.u_a.argv = argv; - chain->u.u_a.index = arg; - chain->u.u_a.flatten = flatten; - chain->u.u_a.has_func = argv->has_func; - chain->u.u_a.comma = false; - chain->u.u_a.skip_last = false; - chain->u.u_a.quotes = m4__quote_cache (M4SYNTAX, obs, chain->quote_age, - quotes); - return value; -} - -/* Given ARGV, return the symbol value at the specified ARG, which - must be non-zero. *LEVEL is set to the obstack level that contains - the symbol (which is not necessarily the level of ARGV). If - FLATTEN, avoid returning a builtin token. */ -static m4_symbol_value * -arg_symbol (m4_macro_args *argv, size_t arg, size_t *level, bool flatten) -{ - size_t i; - m4_symbol_value *value; - - assert (arg); - if (level) - *level = argv->level; - flatten |= argv->flatten; - if (argv->argc <= arg) - return &empty_symbol; - if (!argv->wrapper) - { - value = argv->array[arg - 1]; - if (flatten && m4_is_symbol_value_func (value)) - value = &empty_symbol; - return value; - } - - /* Must cycle through all array slots until we find arg, since - wrappers can contain multiple arguments. */ - for (i = 0; i < argv->arraylen; i++) - { - value = argv->array[i]; - if (value->type == M4_SYMBOL_COMP && value->u.u_c.wrapper) - { - m4__symbol_chain *chain = value->u.u_c.chain; - assert (!chain->next && chain->type == M4__CHAIN_ARGV); - if (arg <= (chain->u.u_a.argv->argc - chain->u.u_a.index - - chain->u.u_a.skip_last)) - { - value = arg_symbol (chain->u.u_a.argv, - chain->u.u_a.index - 1 + arg, level, - flatten || chain->u.u_a.flatten); - break; - } - arg -= (chain->u.u_a.argv->argc - chain->u.u_a.index - - chain->u.u_a.skip_last); - } - else if (--arg == 0) - break; - } - return value; -} - -/* Given ARGV, return the symbol value at the specified ARG, which - must be non-zero. */ -m4_symbol_value * -m4_arg_symbol (m4_macro_args *argv, size_t arg) -{ - return arg_symbol (argv, arg, NULL, false); -} - -/* Given ARGV, return true if argument ARG is text. Arg 0 is always - text, as are indices beyond argc. */ -bool -m4_is_arg_text (m4_macro_args *argv, size_t arg) -{ - m4_symbol_value *value; - if (arg == 0 || argv->argc <= arg || argv->flatten || !argv->has_func) - return true; - value = m4_arg_symbol (argv, arg); - if (m4_is_symbol_value_text (value) - || (value->type == M4_SYMBOL_COMP && !value->u.u_c.has_func)) - return true; - return false; -} - -/* Given ARGV, return true if argument ARG is a single builtin - function. Only non-zero indices less than argc can return - true. */ -bool -m4_is_arg_func (m4_macro_args *argv, size_t arg) -{ - if (arg == 0 || argv->argc <= arg || argv->flatten || !argv->has_func) - return false; - return m4_is_symbol_value_func (m4_arg_symbol (argv, arg)); -} - -/* Given ARGV, return true if argument ARG contains a builtin token - concatenated with anything else. Only non-zero indices less than - argc can return true. */ -bool -m4_is_arg_composite (m4_macro_args *argv, size_t arg) -{ - m4_symbol_value *value; - if (arg == 0 || argv->argc <= arg || argv->flatten || !argv->has_func) - return false; - value = m4_arg_symbol (argv, arg); - if (value->type == M4_SYMBOL_COMP && value->u.u_c.has_func) - return true; - return false; -} - -/* Given ARGV, return the text at argument ARG. Abort if the argument - is not text. Arg 0 is always text, and indices beyond argc return - the empty string. If FLATTEN, builtins are ignored. The result is - always NUL-terminated, even if it includes embedded NUL - characters. */ -const char * -m4_arg_text (m4 *context, m4_macro_args *argv, size_t arg, bool flatten) -{ - m4_symbol_value *value; - m4__symbol_chain *chain; - m4_obstack *obs; - - if (arg == 0) - { - assert (argv->info); - return argv->info->name; - } - if (argv->argc <= arg) - return ""; - value = arg_symbol (argv, arg, NULL, flatten); - if (m4_is_symbol_value_text (value)) - return m4_get_symbol_value_text (value); - assert (value->type == M4_SYMBOL_COMP); - chain = value->u.u_c.chain; - obs = m4_arg_scratch (context); - while (chain) - { - switch (chain->type) - { - case M4__CHAIN_STR: - obstack_grow (obs, chain->u.u_s.str, chain->u.u_s.len); - break; - case M4__CHAIN_FUNC: - if (flatten) - break; - assert (!"m4_arg_text"); - abort (); - case M4__CHAIN_ARGV: - assert (!chain->u.u_a.has_func || flatten || argv->flatten); - m4__arg_print (context, obs, chain->u.u_a.argv, chain->u.u_a.index, - m4__quote_cache (M4SYNTAX, NULL, chain->quote_age, - chain->u.u_a.quotes), - flatten || argv->flatten || chain->u.u_a.flatten, - NULL, NULL, NULL, false, false); - break; - default: - assert (!"m4_arg_text"); - abort (); - } - chain = chain->next; - } - obstack_1grow (obs, '\0'); - return (char *) obstack_finish (obs); -} - -/* Given ARGV, compare text arguments INDEXA and INDEXB for equality. - Both indices must be non-zero. Return true if the arguments - contain the same contents; often more efficient than - STREQ (m4_arg_text (context, argv, indexa), - m4_arg_text (context, argv, indexb)). */ -bool -m4_arg_equal (m4 *context, m4_macro_args *argv, size_t indexa, size_t indexb) -{ - m4_symbol_value *sa = m4_arg_symbol (argv, indexa); - m4_symbol_value *sb = m4_arg_symbol (argv, indexb); - m4__symbol_chain tmpa; - m4__symbol_chain tmpb; - m4__symbol_chain *ca = &tmpa; - m4__symbol_chain *cb = &tmpb; - m4__symbol_chain *chain; - m4_obstack *obs = m4_arg_scratch (context); - - /* Quick tests. */ - if (sa == &empty_symbol || sb == &empty_symbol) - return sa == sb; - if (m4_is_symbol_value_text (sa) && m4_is_symbol_value_text (sb)) - return (m4_get_symbol_value_len (sa) == m4_get_symbol_value_len (sb) - && memcmp (m4_get_symbol_value_text (sa), - m4_get_symbol_value_text (sb), - m4_get_symbol_value_len (sa)) == 0); - - /* Convert both arguments to chains, if not one already. */ - switch (sa->type) - { - case M4_SYMBOL_TEXT: - tmpa.next = NULL; - tmpa.type = M4__CHAIN_STR; - tmpa.u.u_s.str = m4_get_symbol_value_text (sa); - tmpa.u.u_s.len = m4_get_symbol_value_len (sa); - break; - case M4_SYMBOL_FUNC: - tmpa.next = NULL; - tmpa.type = M4__CHAIN_FUNC; - tmpa.u.builtin = sa->u.builtin; - break; - case M4_SYMBOL_COMP: - ca = sa->u.u_c.chain; - break; - default: - assert (!"m4_arg_equal"); - abort (); - } - switch (sb->type) - { - case M4_SYMBOL_TEXT: - tmpb.next = NULL; - tmpb.type = M4__CHAIN_STR; - tmpb.u.u_s.str = m4_get_symbol_value_text (sb); - tmpb.u.u_s.len = m4_get_symbol_value_len (sb); - break; - case M4_SYMBOL_FUNC: - tmpb.next = NULL; - tmpb.type = M4__CHAIN_FUNC; - tmpb.u.builtin = sb->u.builtin; - break; - case M4_SYMBOL_COMP: - cb = sb->u.u_c.chain; - break; - default: - assert (!"m4_arg_equal"); - abort (); - } - - /* Compare each link of the chain. */ - while (ca && cb) - { - if (ca->type == M4__CHAIN_ARGV) - { - tmpa.next = NULL; - tmpa.type = M4__CHAIN_STR; - tmpa.u.u_s.str = NULL; - tmpa.u.u_s.len = 0; - chain = &tmpa; - m4__arg_print (context, obs, ca->u.u_a.argv, ca->u.u_a.index, - m4__quote_cache (M4SYNTAX, NULL, ca->quote_age, - ca->u.u_a.quotes), - argv->flatten || ca->u.u_a.flatten, &chain, NULL, - NULL, false, false); - assert (obstack_object_size (obs) == 0 && chain != &tmpa); - chain->next = ca->next; - ca = tmpa.next; - continue; - } - if (cb->type == M4__CHAIN_ARGV) - { - tmpb.next = NULL; - tmpb.type = M4__CHAIN_STR; - tmpb.u.u_s.str = NULL; - tmpb.u.u_s.len = 0; - chain = &tmpb; - m4__arg_print (context, obs, cb->u.u_a.argv, cb->u.u_a.index, - m4__quote_cache (M4SYNTAX, NULL, cb->quote_age, - cb->u.u_a.quotes), - argv->flatten || cb->u.u_a.flatten, &chain, NULL, - NULL, false, false); - assert (obstack_object_size (obs) == 0 && chain != &tmpb); - chain->next = cb->next; - cb = tmpb.next; - continue; - } - if (ca->type == M4__CHAIN_FUNC) - { - if (cb->type != M4__CHAIN_FUNC || ca->u.builtin != cb->u.builtin) - return false; - ca = ca->next; - cb = cb->next; - continue; - } - assert (ca->type == M4__CHAIN_STR && cb->type == M4__CHAIN_STR); - if (ca->u.u_s.len == cb->u.u_s.len) - { - if (memcmp (ca->u.u_s.str, cb->u.u_s.str, ca->u.u_s.len) != 0) - return false; - ca = ca->next; - cb = cb->next; - } - else if (ca->u.u_s.len < cb->u.u_s.len) - { - if (memcmp (ca->u.u_s.str, cb->u.u_s.str, ca->u.u_s.len) != 0) - return false; - tmpb.next = cb->next; - tmpb.u.u_s.str = cb->u.u_s.str + ca->u.u_s.len; - tmpb.u.u_s.len = cb->u.u_s.len - ca->u.u_s.len; - ca = ca->next; - cb = &tmpb; - } - else - { - assert (cb->u.u_s.len < ca->u.u_s.len); - if (memcmp (ca->u.u_s.str, cb->u.u_s.str, cb->u.u_s.len) != 0) - return false; - tmpa.next = ca->next; - tmpa.u.u_s.str = ca->u.u_s.str + cb->u.u_s.len; - tmpa.u.u_s.len = ca->u.u_s.len - cb->u.u_s.len; - ca = &tmpa; - cb = cb->next; - } - } - - /* If we get this far, the two arguments are equal only if both - chains are exhausted. */ - assert (ca != cb || !ca); - return ca == cb; -} - -/* Given ARGV, return true if argument ARG is the empty string. This - gives the same result as comparing m4_arg_len against 0, but is - often faster. */ -bool -m4_arg_empty (m4_macro_args *argv, size_t arg) -{ - if (!arg) - { - assert (argv->info); - return !argv->info->name_len; - } - return m4_arg_symbol (argv, arg) == &empty_symbol; -} - -/* Given ARGV, return the length of argument ARG. Abort if the - argument is not text and FLATTEN is not true. Indices beyond argc - return 0. */ -size_t -m4_arg_len (m4 *context, m4_macro_args *argv, size_t arg, bool flatten) -{ - m4_symbol_value *value; - m4__symbol_chain *chain; - size_t len; - - if (arg == 0) - { - assert (argv->info); - return argv->info->name_len; - } - if (argv->argc <= arg) - return 0; - value = arg_symbol (argv, arg, NULL, flatten); - if (m4_is_symbol_value_text (value)) - return m4_get_symbol_value_len (value); - assert (value->type == M4_SYMBOL_COMP); - chain = value->u.u_c.chain; - len = 0; - while (chain) - { - size_t i; - size_t limit; - const m4_string_pair *quotes; - switch (chain->type) - { - case M4__CHAIN_STR: - len += chain->u.u_s.len; - break; - case M4__CHAIN_FUNC: - assert (flatten); - break; - case M4__CHAIN_ARGV: - i = chain->u.u_a.index; - limit = chain->u.u_a.argv->argc - i - chain->u.u_a.skip_last; - quotes = m4__quote_cache (M4SYNTAX, NULL, chain->quote_age, - chain->u.u_a.quotes); - assert (limit); - if (quotes) - len += (quotes->len1 + quotes->len2) * limit; - len += limit - 1; - while (limit--) - len += m4_arg_len (context, chain->u.u_a.argv, i++, - flatten || chain->u.u_a.flatten); - break; - default: - assert (!"m4_arg_len"); - abort (); - } - chain = chain->next; - } - assert (len || flatten); - return len; -} - -/* Given ARGV, return the builtin function referenced by argument ARG. - Abort if it is not a single builtin. */ -m4_builtin_func * -m4_arg_func (m4_macro_args *argv, size_t arg) -{ - return m4_get_symbol_value_func (m4_arg_symbol (argv, arg)); -} - -/* Dump a representation of ARGV to the obstack OBS, starting with - argument ARG. If QUOTES is non-NULL, each argument is displayed - with those quotes. If FLATTEN, builtins are converted to empty - quotes; if CHAINP, *CHAINP is updated with macro tokens; otherwise, - builtins are represented by their name. Separate arguments with - SEP, which defaults to a comma. If MAX_LEN is non-NULL, truncate - the output after *MAX_LEN bytes are output and return true; - otherwise, return false, and reduce *MAX_LEN by the number of bytes - output. If QUOTE_EACH, the truncation length is reset for each - argument, quotes do not count against length, and all arguments are - printed; otherwise, quotes count against the length and trailing - arguments may be discarded. If MODULE, print any details about - originating modules; modules do not count against truncation - length. MAX_LEN and CHAINP may not both be specified. */ -bool -m4__arg_print (m4 *context, m4_obstack *obs, m4_macro_args *argv, size_t arg, - const m4_string_pair *quotes, bool flatten, - m4__symbol_chain **chainp, const char *sep, size_t *max_len, - bool quote_each, bool module) -{ - size_t len = max_len ? *max_len : SIZE_MAX; - size_t i; - bool use_sep = false; - size_t sep_len; - size_t *plen = quote_each ? NULL : &len; - - flatten |= argv->flatten; - if (chainp) - assert (!max_len && *chainp); - if (!sep) - sep = ","; - sep_len = strlen (sep); - for (i = arg; i < argv->argc; i++) - { - if (quote_each && max_len) - len = *max_len; - if (use_sep && m4_shipout_string_trunc (obs, sep, sep_len, NULL, plen)) - return true; - use_sep = true; - if (quotes && !quote_each - && m4_shipout_string_trunc (obs, quotes->str1, quotes->len1, NULL, - plen)) - return true; - if (m4__symbol_value_print (context, arg_symbol (argv, i, NULL, flatten), - obs, quote_each ? quotes : NULL, flatten, - chainp, &len, module)) - return true; - if (quotes && !quote_each - && m4_shipout_string_trunc (obs, quotes->str2, quotes->len2, NULL, - plen)) - return true; - } - if (max_len) - *max_len = len; - else if (chainp) - m4__make_text_link (obs, NULL, chainp); - return false; -} - -/* Create a new argument object using the same obstack as ARGV; thus, - the new object will automatically be freed when the original is - freed. Explicitly set the macro name (argv[0]) from ARGV0 with - length ARGV0_LEN, and discard argv[1] of the wrapped ARGV. If - FLATTEN, any builtins in ARGV are flattened to an empty string when - referenced through the new object. If TRACE, then trace the macro - regardless of global trace state. */ -m4_macro_args * -m4_make_argv_ref (m4 *context, m4_macro_args *argv, const char *argv0, - size_t argv0_len, bool flatten, bool trace) -{ - m4_macro_args *new_argv; - m4_symbol_value *value; - m4_symbol_value *new_value; - m4_obstack *obs = m4_arg_scratch (context); - m4_call_info *info; - - info = (m4_call_info *) obstack_copy (obs, argv->info, sizeof *info); - new_value = (m4_symbol_value *) obstack_alloc (obs, sizeof *value); - value = make_argv_ref (context, new_value, obs, context->expansion_level - 1, - argv, 2, flatten, NULL); - if (!value) - { - obstack_free (obs, new_value); - new_argv = (m4_macro_args *) obstack_alloc (obs, offsetof (m4_macro_args, - array)); - new_argv->arraylen = 0; - new_argv->wrapper = false; - new_argv->has_ref = false; - new_argv->flatten = false; - new_argv->has_func = false; - } - else - { - new_argv = (m4_macro_args *) obstack_alloc (obs, (offsetof (m4_macro_args, - array) - + sizeof value)); - new_argv->arraylen = 1; - new_argv->array[0] = value; - new_argv->wrapper = true; - new_argv->has_ref = argv->has_ref; - new_argv->flatten = flatten; - new_argv->has_func = argv->has_func; - } - new_argv->argc = argv->argc - 1; - new_argv->inuse = false; - new_argv->quote_age = argv->quote_age; - new_argv->info = info; - info->trace = (argv->info->debug_level & M4_DEBUG_TRACE_ALL) || trace; - info->name = argv0; - info->name_len = argv0_len; - new_argv->level = argv->level; - return new_argv; -} - -/* Push argument ARG from ARGV, which must be a text token, onto the - expansion stack OBS for rescanning. */ -void -m4_push_arg (m4 *context, m4_obstack *obs, m4_macro_args *argv, size_t arg) -{ - m4_symbol_value value; - - if (arg == 0) - { - assert (argv->info); - m4_set_symbol_value_text (&value, argv->info->name, argv->info->name_len, - 0); - if (m4__push_symbol (context, &value, context->expansion_level - 1, - argv->inuse)) - arg_mark (argv); - } - else - m4__push_arg_quote (context, obs, argv, arg, NULL); -} - -/* Push argument ARG from ARGV onto the expansion stack OBS for - rescanning. ARG must be non-zero. QUOTES determines any quote - delimiters that were in effect when the reference was created. */ -void -m4__push_arg_quote (m4 *context, m4_obstack *obs, m4_macro_args *argv, - size_t arg, const m4_string_pair *quotes) -{ - size_t level; - m4_symbol_value *value = arg_symbol (argv, arg, &level, false); - - if (quotes) - obstack_grow (obs, quotes->str1, quotes->len1); - if (value != &empty_symbol - && m4__push_symbol (context, value, level, argv->inuse)) - arg_mark (argv); - if (quotes) - obstack_grow (obs, quotes->str2, quotes->len2); -} - -/* Push series of comma-separated arguments from ARGV onto the - expansion stack OBS for rescanning. If SKIP, then don't push the - first argument. If QUOTE, also push quoting around each arg. */ -void -m4_push_args (m4 *context, m4_obstack *obs, m4_macro_args *argv, bool skip, - bool quote) -{ - m4_symbol_value tmp; - m4_symbol_value *value; - size_t i = skip ? 2 : 1; - const m4_string_pair *quotes = m4_get_syntax_quotes (M4SYNTAX); - - if (argv->argc <= i) - return; - - if (argv->argc == i + 1) - { - m4__push_arg_quote (context, obs, argv, i, quote ? quotes : NULL); - return; - } - - value = make_argv_ref (context, &tmp, obs, -1, argv, i, argv->flatten, - quote ? quotes : NULL); - assert (value == &tmp); - if (m4__push_symbol (context, value, -1, argv->inuse)) - arg_mark (argv); -} - -/* Push arguments from ARGV onto the wrap stack for later rescanning. - If GNU extensions are disabled, only the first argument is pushed; - otherwise, all arguments are pushed and separated with a space. */ -void -m4_wrap_args (m4 *context, m4_macro_args *argv) -{ - size_t i; - m4_obstack *obs; - m4_symbol_value *value; - m4__symbol_chain *chain; - m4__symbol_chain **end; - size_t limit = m4_get_posixly_correct_opt (context) ? 2 : argv->argc; - - if (limit == 2 && m4_arg_empty (argv, 1)) - return; - - obs = m4__push_wrapup_init (context, argv->info, &end); - for (i = 1; i < limit; i++) - { - if (i != 1) - obstack_1grow (obs, ' '); - value = m4_arg_symbol (argv, i); - switch (value->type) - { - case M4_SYMBOL_TEXT: - obstack_grow (obs, m4_get_symbol_value_text (value), - m4_get_symbol_value_len (value)); - break; - case M4_SYMBOL_FUNC: - m4__append_builtin (obs, value->u.builtin, NULL, end); - break; - case M4_SYMBOL_COMP: - chain = value->u.u_c.chain; - while (chain) - { - switch (chain->type) - { - case M4__CHAIN_STR: - obstack_grow (obs, chain->u.u_s.str, chain->u.u_s.len); - break; - case M4__CHAIN_FUNC: - m4__append_builtin (obs, chain->u.builtin, NULL, end); - break; - case M4__CHAIN_ARGV: - m4__arg_print (context, obs, chain->u.u_a.argv, - chain->u.u_a.index, - m4__quote_cache (M4SYNTAX, NULL, - chain->quote_age, - chain->u.u_a.quotes), - chain->u.u_a.flatten, end, NULL, NULL, false, - false); - break; - default: - assert (!"m4_wrap_args"); - abort (); - } - chain = chain->next; - } - break; - default: - assert (!"m4_wrap_args"); - abort (); - } - } - m4__push_wrapup_finish (); -} - - -/* Define these last, so that earlier uses can benefit from the macros - in m4private.h. */ - -/* Given ARGV, return one greater than the number of arguments it - describes. */ -#undef m4_arg_argc -size_t -m4_arg_argc (m4_macro_args *argv) -{ - return argv->argc; -} - -/* Given ARGV, return the call context in effect when argument - collection began. Only safe to call while the macro is being - expanded. */ -#undef m4_arg_info -const m4_call_info * -m4_arg_info (m4_macro_args *argv) -{ - assert (argv->info); - return argv->info; -} - -/* Return an obstack useful for scratch calculations, and which will - not interfere with macro expansion. The obstack will be reset when - expand_macro completes. */ -#undef m4_arg_scratch -m4_obstack * -m4_arg_scratch (m4 *context) -{ - m4__macro_arg_stacks *stack - = &context->arg_stacks[context->expansion_level - 1]; - assert (obstack_object_size (stack->args) == 0); - return stack->args; -} diff --git a/m4/module.c b/m4/module.c deleted file mode 100644 index c00b8aa1..00000000 --- a/m4/module.c +++ /dev/null @@ -1,344 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 1998-1999, 2002-2008, 2010, 2013-2014, 2017 - 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 . -*/ - -#include - -#include - -#include "m4private.h" -#include "xvasprintf.h" - -/* Define this to see runtime debug info. Implied by DEBUG. */ -/*#define DEBUG_MODULES */ - -/* - * This file implements dynamic modules in GNU M4. A module is a - * compiled shared object, that can be loaded into GNU M4 at run - * time. Information about creating modules is in ../modules/README. - * - * This implementation uses libltdl, which is in turn can open modules - * using either dlopen(3) (exists on GNU/Linux, OSF, Solaris, SunOS and - * others), shl_load(3) (exists on HPUX), LoadLibrary(3) (exists on - * Windows, cygwin, OS/2), load_add_on(3) (exists on BeOS), NSAddImage - * (exists on MacOS) and can also fall back to dld_link(3) from GNU - * libdld or lt_dlpreload from libtool if shared libraries are not - * available on the host machine. - * - * An M4 module will usually define an external symbol named after the - * basename of the loadable module: - * - * void - * mymod_LTX_m4_init_module (m4 *context, m4_module *module, - * m4_obstack *obs) - * - * The function is only called the first time the module is included - * and generally uses either `m4_install_builtins' or - * `m4_install_macros' (or both!) to register whatever builtins and - * macros are provided by the module. - * - * To load a module, call m4_module_load(), which searches for the - * module in directories from M4PATH. The search path is initialized - * from the environment variable M4PATH, followed by the configuration - * time default where the modules shipped with M4 itself are installed. - * `m4_module_load' returns NULL on failure, or else an opaque module - * handle for the newly mapped vm segment containing the module code. - * If the module is not already loaded, m4_module_load() the builtins - * and macros registered by `mymod_LTX_m4_init_module' are installed - * into the symbol table using `install_builtin_table' and `install_ - * macro_table' respectively. - **/ - -#define MODULE_SELF_NAME "!myself!" - -#if DLSYM_USCORE -static void * -uscore_sym (void *handle, const char *symbol) -{ - char *symname = xasprintf ("_%s", symbol); - void *address = dlsym (handle, symname); - free (symname); - return address; -} - -#define dlsym uscore_sym -#endif - -static const char * module_dlerror (void); - -static void install_builtin_table (m4*, m4_module *); -static void install_macro_table (m4*, m4_module *); - -static int compare_builtin_CB (const void *a, const void *b); - -const char * -m4_get_module_name (const m4_module *module) -{ - assert (module); - return module->name; -} - -void * -m4_module_import (m4 *context, const char *module_name, - const char *symbol_name, m4_obstack *obs) -{ - m4_module * module = m4__module_find (context, module_name); - void * symbol_address = NULL; - - /* Try to load the module if it is not yet available (errors are - diagnosed by m4_module_load). */ - /* FIXME - should this use m4__module_open instead, to avoid - polluting the symbol table when importing a function? */ - if (!module) - module = m4_module_load (context, module_name, obs); - - if (module) - { - symbol_address = dlsym (module->handle, symbol_name); - - if (!symbol_address) - m4_error (context, 0, 0, NULL, - _("cannot load symbol `%s' from module `%s'"), - symbol_name, module_name); - } - - return symbol_address; -} - -void -m4_install_builtins (m4 *context, m4_module *module, const m4_builtin *bp) -{ - assert (context); - assert (module); - assert (bp); - - const m4_builtin *tmp; - m4__builtin *builtin; - for (tmp = bp; tmp->name; tmp++) - module->builtins_len++; - module->builtins = (m4__builtin *) xnmalloc (module->builtins_len, - sizeof *module->builtins); - for (builtin = module->builtins; bp->name != NULL; bp++, builtin++) - { - /* Sanity check that builtins meet the required interface. */ - assert (bp->min_args <= bp->max_args); - assert (bp->min_args > 0 || - (bp->flags & (M4_BUILTIN_BLIND|M4_BUILTIN_SIDE_EFFECT)) == 0); - assert (bp->max_args || - (bp->flags & M4_BUILTIN_FLATTEN_ARGS) == 0); - assert ((bp->flags & ~M4_BUILTIN_FLAGS_MASK) == 0); - memcpy (&builtin->builtin, bp, sizeof *bp); - builtin->builtin.name = xstrdup (bp->name); - builtin->module = module; - } - qsort (module->builtins, module->builtins_len, - sizeof *module->builtins, compare_builtin_CB); -} - -static void -install_builtin_table (m4 *context, m4_module *module) -{ - size_t i; - - assert (context); - assert (module); - for (i = 0; i < module->builtins_len; i++) - { - m4_symbol_value *value = m4_symbol_value_create (); - const char *name = module->builtins[i].builtin.name; - - m4__set_symbol_value_builtin (value, &module->builtins[i]); - if (m4_get_prefix_builtins_opt (context)) - name = xasprintf ("m4_%s", name); - - m4_symbol_pushdef (M4SYMTAB, name, strlen (name), value); - - if (m4_get_prefix_builtins_opt (context)) - DELETE (name); - } - if (i) - m4_debug_message (context, M4_DEBUG_TRACE_MODULE, - _("module %s: builtins loaded"), - m4_get_module_name (module)); -} - -void -m4_install_macros (m4 *context, m4_module *module, const m4_macro *mp) -{ - assert (context); - assert (module); - assert (mp); - - module->macros = (m4_macro *) mp; -} - -static void -install_macro_table (m4 *context, m4_module *module) -{ - const m4_macro *mp; - - assert (context); - assert (module); - - mp = module->macros; - - if (mp) - { - for (; mp->name != NULL; mp++) - { - m4_symbol_value *value = m4_symbol_value_create (); - size_t len = strlen (mp->value); - - /* Sanity check that builtins meet the required interface. */ - assert (mp->min_args <= mp->max_args); - - m4_set_symbol_value_text (value, xmemdup0 (mp->value, len), len, 0); - VALUE_MODULE (value) = module; - VALUE_MIN_ARGS (value) = mp->min_args; - VALUE_MAX_ARGS (value) = mp->max_args; - - m4_symbol_pushdef (M4SYMTAB, mp->name, strlen (mp->name), value); - } - - m4_debug_message (context, M4_DEBUG_TRACE_MODULE, - _("module %s: macros loaded"), - m4_get_module_name (module)); - } -} - -m4_module * -m4_module_load (m4 *context, const char *name, m4_obstack *obs) -{ - m4_module *module = m4__module_find (context, name); - - if (!module) - { - module = m4__module_open (context, name, obs); - - if (module) - { - install_builtin_table (context, module); - install_macro_table (context, module); - } - } - - return module; -} - - -/* Return successive loaded modules. */ -m4_module * -m4_module_next (m4 *context, m4_module *module) -{ - return module ? module->next : context->modules; -} - -/* Return the first loaded module that passes the registered interface test - and is called NAME. */ -m4_module * -m4__module_find (m4 *context, const char *name) -{ - m4_module **pmodule = (m4_module **) m4_hash_lookup (context->namemap, name); - return pmodule ? *pmodule : NULL; -} - - -/* Compare two builtins A and B for sorting, as in qsort. */ -static int -compare_builtin_CB (const void *a, const void *b) -{ - const m4__builtin *builtin_a = (const m4__builtin *) a; - const m4__builtin *builtin_b = (const m4__builtin *) b; - int result = strcmp (builtin_a->builtin.name, builtin_b->builtin.name); - /* A builtin module should never provide two builtins with the same - name. */ - assert (result || a == b); - return result; -} - -/* Load a module. NAME can be a absolute file name or, if relative, - it is searched for in the module path. The module is unloaded in - case of error. */ -m4_module * -m4__module_open (m4 *context, const char *name, m4_obstack *obs) -{ - static const char * suffixes[] = { "", LT_MODULE_EXT, NULL }; - m4_module * module = NULL; - - assert (context); - - char *filepath = m4_path_search (context, name, suffixes); - void *handle = NULL; - - if (filepath) - { - handle = dlopen (filepath, RTLD_NOW|RTLD_GLOBAL); - free (filepath); - } - - if (handle) - { - m4_debug_message (context, M4_DEBUG_TRACE_MODULE, - _("module %s: opening file %s"), - name ? name : MODULE_SELF_NAME, - quotearg_style (locale_quoting_style, name)); - - module = (m4_module *) xzalloc (sizeof *module); - module->name = xstrdup (name); - module->handle = handle; - module->next = context->modules; - - context->modules = module; - m4_hash_insert (context->namemap, xstrdup (name), module); - - /* Find and run any initializing function in the opened module, - the first time the module is opened. */ - char *entry_point = xasprintf ("include_%s", name); - m4_module_init_func *init_func = - (m4_module_init_func *) dlsym (handle, entry_point); - free (entry_point); - - if (init_func) - { - init_func (context, module, obs); - - m4_debug_message (context, M4_DEBUG_TRACE_MODULE, - _("module %s: init hook called"), name); - } - else - { - m4_error (context, EXIT_FAILURE, 0, NULL, - _("module `%s' has no entry point"), name); - } - - m4_debug_message (context, M4_DEBUG_TRACE_MODULE, - _("module %s: opened"), name); - } - else - { - const char *err = dlerror (); - if (!err) err = _("unknown error"); - - /* Couldn't open the module; diagnose and exit. */ - m4_error (context, EXIT_FAILURE, 0, NULL, - _("cannot open module `%s': %s"), name, err); - } - - return module; -} diff --git a/m4/output.c b/m4/output.c deleted file mode 100644 index b9371956..00000000 --- a/m4/output.c +++ /dev/null @@ -1,1119 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 1998, 2002, 2004, 2006-2010, 2013-2014, 2017 - 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 . -*/ - -#include - -#include - -#include "m4private.h" - -#include "binary-io.h" -#include "clean-temp.h" -#include "exitfail.h" -#include "gl_avltree_oset.h" -#include "gl_xoset.h" -#include "intprops.h" -#include "quotearg.h" -#include "xvasprintf.h" - -/* Define this to see runtime debug output. Implied by DEBUG. */ -/*#define DEBUG_OUTPUT */ - -/* Size of initial in-memory buffer size for diversions. Small diversions - would usually fit in. */ -#define INITIAL_BUFFER_SIZE 512 - -/* Maximum value for the total of all in-memory buffer sizes for - diversions. */ -#define MAXIMUM_TOTAL_SIZE (512 * 1024) - -/* Size of buffer size to use while copying files. */ -#define COPY_BUFFER_SIZE (32 * 512) - -/* Output functions. Most of the complexity is for handling cpp like - sync lines. - - This code is fairly entangled with the code in input.c, and maybe it - belongs there? */ - -typedef struct temp_dir m4_temp_dir; - -/* When part of diversion_table, each struct m4_diversion either - represents an open file (zero size, non-NULL u.file), an in-memory - buffer (non-zero size, non-NULL u.buffer), or an unused placeholder - diversion (zero size, u is NULL, non-zero used indicates that a - temporary file exists). When not part of diversion_table, u.next - is a pointer to the free_list chain. */ - -typedef struct m4_diversion m4_diversion; - -struct m4_diversion - { - union - { - FILE *file; /* Diversion file on disk. */ - char *buffer; /* Malloc'd diversion buffer. */ - m4_diversion *next; /* Free-list pointer */ - } u; - int divnum; /* Which diversion this represents. */ - size_t size; /* Usable size before reallocation. */ - size_t used; /* Used buffer length, or tmp file exists. */ - }; - -/* Sorted set of diversions 1 through INT_MAX. */ -static gl_oset_t diversion_table; - -/* Diversion 0 (not part of diversion_table). */ -static m4_diversion div0; - -/* Linked list of reclaimed diversion storage. */ -static m4_diversion *free_list; - -/* Obstack from which diversion storage is allocated. */ -static m4_obstack diversion_storage; - -/* Total size of all in-memory buffer sizes. */ -static size_t total_buffer_size; - -/* Current output diversion, NULL if output is being currently - discarded. output_diversion->u is guaranteed non-NULL except when - the diversion has never been used; use size to determine if it is a - malloc'd buffer or a FILE. output_diversion->used is 0 if u.file - is stdout, and non-zero if this is a malloc'd buffer or a temporary - diversion file. */ -static m4_diversion *output_diversion; - -/* Cache of output_diversion->u.file, only valid when - output_diversion->size is 0. */ -static FILE *output_file; - -/* Cache of output_diversion->u.buffer + output_diversion->used, only - valid when output_diversion->size is non-zero. */ -static char *output_cursor; - -/* Cache of output_diversion->size - output_diversion->used, only - valid when output_diversion->size is non-zero. */ -static size_t output_unused; - -/* Temporary directory holding all spilled diversion files. */ -static m4_temp_dir *output_temp_dir; - -/* Cache of most recently used spilled diversion files. */ -static FILE *tmp_file1; -static FILE *tmp_file2; - -/* Diversions that own tmp_file, or 0. */ -static int tmp_file1_owner; -static int tmp_file2_owner; - -/* True if tmp_file2 is more recently used. */ -static bool tmp_file2_recent; - - -/* Internal routines. */ - -/* Callback for comparing list elements ELT1 and ELT2 for order in - diversion_table. */ -static int -cmp_diversion_CB (const void *elt1, const void *elt2) -{ - const m4_diversion *d1 = (const m4_diversion *) elt1; - const m4_diversion *d2 = (const m4_diversion *) elt2; - /* No need to worry about overflow, since we don't create diversions - with negative divnum. */ - return d1->divnum - d2->divnum; -} - -/* Callback for comparing list element ELT against THRESHOLD. */ -static bool -threshold_diversion_CB (const void *elt, const void *threshold) -{ - const m4_diversion *diversion = (const m4_diversion *) elt; - /* No need to worry about overflow, since we don't create diversions - with negative divnum. */ - return diversion->divnum >= *(const int *) threshold; -} - -/* Clean up any temporary directory. Designed for use as an atexit - handler, where it is not safe to call exit() recursively; so this - calls _exit if a problem is encountered. */ -static void -cleanup_tmpfile (void) -{ - /* Close any open diversions. */ - bool fail = false; - - if (diversion_table) - { - const void *elt; - gl_oset_iterator_t iter = gl_oset_iterator (diversion_table); - while (gl_oset_iterator_next (&iter, &elt)) - { - m4_diversion *diversion = (m4_diversion *) elt; - if (!diversion->size && diversion->u.file - && close_stream_temp (diversion->u.file) != 0) - { - error (0, errno, - _("cannot clean temporary file for diversion")); - fail = true; - } - } - gl_oset_iterator_free (&iter); - } - - /* Clean up the temporary directory. */ - if (cleanup_temp_dir (output_temp_dir) != 0) - fail = true; - if (fail) - _exit (exit_failure); -} - -/* Convert DIVNUM into a temporary file name for use in m4_tmp*. */ -static const char * -m4_tmpname (int divnum) -{ - static char *buffer; - static size_t offset; - if (buffer == NULL) - { - obstack_printf (&diversion_storage, "%s/m4-", output_temp_dir->dir_name); - offset = obstack_object_size (&diversion_storage); - buffer = (char *) obstack_alloc (&diversion_storage, - INT_BUFSIZE_BOUND (divnum)); - } - assert (0 < divnum); - if (snprintf (&buffer[offset], INT_BUFSIZE_BOUND (divnum), "%d", divnum) < 0) - abort (); - return buffer; -} - -/* Create a temporary file for diversion DIVNUM open for reading and - writing in a secure temp directory. The file will be automatically - closed and deleted on a fatal signal. The file can be closed and - reopened with m4_tmpclose and m4_tmpopen, or moved with - m4_tmprename; when finally done with the file, close it with - m4_tmpremove. Exits on failure, so the return value is always an - open file. */ -static FILE * -m4_tmpfile (m4 *context, int divnum) -{ - const char *name; - FILE *file; - - if (output_temp_dir == NULL) - { - output_temp_dir = create_temp_dir ("m4-", NULL, true); - if (output_temp_dir == NULL) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("cannot create temporary file for diversion")); - atexit (cleanup_tmpfile); - } - name = m4_tmpname (divnum); - register_temp_file (output_temp_dir, name); - file = fopen_temp (name, O_BINARY ? "wb+" : "w+"); - if (file == NULL) - { - unregister_temp_file (output_temp_dir, name); - m4_error (context, EXIT_FAILURE, errno, NULL, - _("cannot create temporary file for diversion")); - } - else if (set_cloexec_flag (fileno (file), true) != 0) - m4_warn (context, errno, NULL, _("cannot protect diversion across forks")); - return file; -} - -/* Reopen a temporary file for diversion DIVNUM for reading and - writing in a secure temp directory. If REREAD, the file is - positioned at offset 0, otherwise the file is positioned at the - end. Exits on failure, so the return value is always an open - file. */ -static FILE * -m4_tmpopen (m4 *context, int divnum, bool reread) -{ - const char *name; - FILE *file; - - if (tmp_file1_owner == divnum) - { - if (reread && fseeko (tmp_file1, 0, SEEK_SET) != 0) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("cannot seek within diversion")); - tmp_file2_recent = false; - return tmp_file1; - } - else if (tmp_file2_owner == divnum) - { - if (reread && fseeko (tmp_file2, 0, SEEK_SET) != 0) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("cannot seek to beginning of diversion")); - tmp_file2_recent = true; - return tmp_file2; - } - name = m4_tmpname (divnum); - /* We need update mode, to avoid truncation. */ - file = fopen_temp (name, O_BINARY ? "rb+" : "r+"); - if (file == NULL) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("cannot create temporary file for diversion")); - else if (set_cloexec_flag (fileno (file), true) != 0) - m4_warn (context, errno, NULL, _("cannot protect diversion across forks")); - /* Update mode starts at the beginning of the stream, but sometimes - we want the end. */ - else if (!reread && fseeko (file, 0, SEEK_END) != 0) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("cannot seek within diversion")); - return file; -} - -/* Close, but don't delete, a temporary FILE for diversion DIVNUM. To - reduce the I/O overhead of repeatedly opening and closing the same - file, this implementation caches the most recent spilled diversion. - On the other hand, keeping every spilled diversion open would run - into EMFILE limits. */ -static int -m4_tmpclose (FILE *file, int divnum) -{ - int result = 0; - if (divnum != tmp_file1_owner && divnum != tmp_file2_owner) - { - if (tmp_file2_recent) - { - if (tmp_file1_owner) - result = close_stream_temp (tmp_file1); - tmp_file1 = file; - tmp_file1_owner = divnum; - } - else - { - if (tmp_file2_owner) - result = close_stream_temp (tmp_file2); - tmp_file2 = file; - tmp_file2_owner = divnum; - } - } - return result; -} - -/* Delete a closed temporary FILE for diversion DIVNUM. */ -static int -m4_tmpremove (int divnum) -{ - if (divnum == tmp_file1_owner) - { - int result = close_stream_temp (tmp_file1); - if (result) - return result; - tmp_file1_owner = 0; - } - else if (divnum == tmp_file2_owner) - { - int result = close_stream_temp (tmp_file2); - if (result) - return result; - tmp_file2_owner = 0; - } - return cleanup_temp_file (output_temp_dir, m4_tmpname (divnum)); -} - -/* Transfer the temporary file for diversion OLDNUM to the previously - unused diversion NEWNUM. Return an open stream visiting the new - temporary file, positioned at the end, or exit on failure. */ -static FILE* -m4_tmprename (m4 *context, int oldnum, int newnum) -{ - /* m4_tmpname reuses its return buffer. */ - char *oldname = xstrdup (m4_tmpname (oldnum)); - const char *newname = m4_tmpname (newnum); - register_temp_file (output_temp_dir, newname); - if (oldnum == tmp_file1_owner) - { - /* Be careful of mingw, which can't rename an open file. */ - if (RENAME_OPEN_FILE_WORKS) - tmp_file1_owner = newnum; - else - { - if (close_stream_temp (tmp_file1)) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("cannot close temporary file for diversion")); - tmp_file1_owner = 0; - } - } - else if (oldnum == tmp_file2_owner) - { - /* Be careful of mingw, which can't rename an open file. */ - if (RENAME_OPEN_FILE_WORKS) - tmp_file2_owner = newnum; - else - { - if (close_stream_temp (tmp_file2)) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("cannot close temporary file for diversion")); - tmp_file2_owner = 0; - } - } - /* Either it is safe to rename an open file, or no one should have - oldname open at this point. */ - if (rename (oldname, newname)) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("cannot create temporary file for diversion")); - unregister_temp_file (output_temp_dir, oldname); - free (oldname); - return m4_tmpopen (context, newnum, false); -} - - -/* --- OUTPUT INITIALIZATION --- */ - -/* Initialize the output engine. */ -void -m4_output_init (m4 *context) -{ - diversion_table = gl_oset_create_empty (GL_AVLTREE_OSET, cmp_diversion_CB, - NULL); - div0.u.file = stdout; - m4_set_current_diversion (context, 0); - output_diversion = &div0; - output_file = stdout; - obstack_init (&diversion_storage); -} - -/* Clean up memory allocated during use. */ -void -m4_output_exit (void) -{ - /* Order is important, since we may have registered cleanup_tmpfile - as an atexit handler, and it must not traverse stale memory. */ - gl_oset_t table = diversion_table; - assert (gl_oset_size (diversion_table) == 0); - if (tmp_file1_owner) - m4_tmpremove (tmp_file1_owner); - if (tmp_file2_owner) - m4_tmpremove (tmp_file2_owner); - diversion_table = NULL; - gl_oset_free (table); - obstack_free (&diversion_storage, NULL); -} - -/* Reorganize in-memory diversion buffers so the current diversion can - accomodate LENGTH more characters without further reorganization. The - current diversion buffer is made bigger if possible. But to make room - for a bigger buffer, one of the in-memory diversion buffers might have - to be flushed to a newly created temporary file. This flushed buffer - might well be the current one. */ -static void -make_room_for (m4 *context, size_t length) -{ - size_t wanted_size; - m4_diversion *selected_diversion = NULL; - - assert (!output_file); - assert (output_diversion); - assert (output_diversion->size || !output_diversion->u.file); - - /* Compute needed size for in-memory buffer. Diversions in-memory - buffers start at 0 bytes, then 512, then keep doubling until it is - decided to flush them to disk. */ - - output_diversion->used = output_diversion->size - output_unused; - - for (wanted_size = output_diversion->size; - wanted_size <= MAXIMUM_TOTAL_SIZE - && wanted_size - output_diversion->used < length; - wanted_size = wanted_size == 0 ? INITIAL_BUFFER_SIZE : wanted_size * 2) - ; - - /* Check if we are exceeding the maximum amount of buffer memory. */ - - if (total_buffer_size - output_diversion->size + wanted_size - > MAXIMUM_TOTAL_SIZE) - { - size_t selected_used; - char *selected_buffer; - m4_diversion *diversion; - size_t count; - gl_oset_iterator_t iter; - const void *elt; - - /* Find out the buffer having most data, in view of flushing it to - disk. Fake the current buffer as having already received the - projected data, while making the selection. So, if it is - selected indeed, we will flush it smaller, before it grows. */ - - selected_diversion = output_diversion; - selected_used = output_diversion->used + length; - - iter = gl_oset_iterator (diversion_table); - while (gl_oset_iterator_next (&iter, &elt)) - { - diversion = (m4_diversion *) elt; - if (diversion->used > selected_used) - { - selected_diversion = diversion; - selected_used = diversion->used; - } - } - gl_oset_iterator_free (&iter); - - /* Create a temporary file, write the in-memory buffer of the - diversion to this file, then release the buffer. Zero the - diversion before doing anything that can exit () (including - m4_tmpfile), so that the atexit handler doesn't try to close - a garbage pointer as a file. */ - - selected_buffer = selected_diversion->u.buffer; - total_buffer_size -= selected_diversion->size; - selected_diversion->size = 0; - selected_diversion->u.file = NULL; - selected_diversion->u.file = m4_tmpfile (context, - selected_diversion->divnum); - - if (selected_diversion->used > 0) - { - count = fwrite (selected_buffer, selected_diversion->used, 1, - selected_diversion->u.file); - if (count != 1) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("cannot flush diversion to temporary file")); - } - - /* Reclaim the buffer space for other diversions. */ - - free (selected_buffer); - selected_diversion->used = 1; - } - - /* Reload output_file, just in case the flushed diversion was current. */ - - if (output_diversion == selected_diversion) - { - /* The flushed diversion was current indeed. */ - - output_file = output_diversion->u.file; - output_cursor = NULL; - output_unused = 0; - } - else - { - /* Close any selected file since it is not the current diversion. */ - if (selected_diversion) - { - FILE *file = selected_diversion->u.file; - selected_diversion->u.file = NULL; - if (m4_tmpclose (file, selected_diversion->divnum) != 0) - m4_error (context, 0, errno, NULL, - _("cannot close temporary file for diversion")); - } - - /* The current buffer may be safely reallocated. */ - assert (wanted_size >= length); - { - char *buffer = output_diversion->u.buffer; - output_diversion->u.buffer = xcharalloc ((size_t) wanted_size); - memcpy (output_diversion->u.buffer, buffer, output_diversion->used); - free (buffer); - } - - total_buffer_size += wanted_size - output_diversion->size; - output_diversion->size = wanted_size; - - output_cursor = output_diversion->u.buffer + output_diversion->used; - output_unused = wanted_size - output_diversion->used; - } -} - -/* Output one character CHAR, when it is known that it goes to a - diversion file or an in-memory diversion buffer. A variable m4 - *context must be in scope. */ -#define OUTPUT_CHARACTER(Char) \ - if (output_file) \ - putc ((Char), output_file); \ - else if (output_unused == 0) \ - output_character_helper (context, (Char)); \ - else \ - (output_unused--, *output_cursor++ = (Char)) - -static void -output_character_helper (m4 *context, int character) -{ - make_room_for (context, 1); - - if (output_file) - putc (character, output_file); - else - { - *output_cursor++ = character; - output_unused--; - } -} - -/* Output one TEXT having LENGTH characters, when it is known that it goes - to a diversion file or an in-memory diversion buffer. */ -void -m4_output_text (m4 *context, const char *text, size_t length) -{ - size_t count; - - if (!output_diversion || !length) - return; - - if (!output_file && length > output_unused) - make_room_for (context, length); - - if (output_file) - { - count = fwrite (text, length, 1, output_file); - if (count != 1) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("copying inserted file")); - } - else - { - memcpy (output_cursor, text, length); - output_cursor += length; - output_unused -= length; - } -} - -/* Add some text into an obstack OBS, taken from TEXT, having LENGTH - characters. If OBS is NULL, output the text to an external file or - an in-memory diversion buffer instead. If OBS is NULL, and there - is no output file, the text is discarded. LINE is the line where - the token starts (not necessarily m4_get_output_line, in the case - of multiline tokens). - - If we are generating sync lines, the output has to be examined, - because we need to know how much output each input line generates. - In general, sync lines are output whenever a single input line - generates several output lines, or when several input lines do not - generate any output. */ -void -m4_divert_text (m4 *context, m4_obstack *obs, const char *text, size_t length, - int line) -{ - static bool start_of_output_line = true; - - /* If output goes to an obstack, merely add TEXT to it. */ - - if (obs != NULL) - { - obstack_grow (obs, text, length); - return; - } - - /* Do nothing if TEXT should be discarded. */ - - if (!output_diversion || !length) - return; - - /* Output TEXT to a file, or in-memory diversion buffer. */ - - if (!m4_get_syncoutput_opt (context)) - switch (length) - { - - /* In-line short texts. */ - - case 8: OUTPUT_CHARACTER (*text); text++; - case 7: OUTPUT_CHARACTER (*text); text++; - case 6: OUTPUT_CHARACTER (*text); text++; - case 5: OUTPUT_CHARACTER (*text); text++; - case 4: OUTPUT_CHARACTER (*text); text++; - case 3: OUTPUT_CHARACTER (*text); text++; - case 2: OUTPUT_CHARACTER (*text); text++; - case 1: OUTPUT_CHARACTER (*text); - case 0: - return; - - /* Optimize longer texts. */ - - default: - m4_output_text (context, text, length); - } - else - { - /* Check for syncline only at the start of a token. Multiline - tokens, and tokens that are out of sync but in the middle of - the line, must wait until the next raw newline triggers a - syncline. */ - if (start_of_output_line) - { - start_of_output_line = false; - m4_set_output_line (context, m4_get_output_line (context) + 1); - -#ifdef DEBUG_OUTPUT - xfprintf (stderr, "DEBUG: line %d, cur %lu, cur out %lu\n", line, - (unsigned long int) m4_get_current_line (context), - (unsigned long int) m4_get_output_line (context)); -#endif - - /* Output a `#line NUM' synchronization directive if needed. - If output_line was previously given a negative - value (invalidated), then output `#line NUM "FILE"'. */ - - if (m4_get_output_line (context) != line) - { - char linebuf[sizeof "#line " + INT_BUFSIZE_BOUND (line)]; - sprintf (linebuf, "#line %lu", - (unsigned long int) m4_get_current_line (context)); - m4_output_text (context, linebuf, strlen (linebuf)); - if (m4_get_output_line (context) < 1 - && m4_get_current_file (context)[0] != '\0') - { - const char *file = m4_get_current_file (context); - OUTPUT_CHARACTER (' '); - OUTPUT_CHARACTER ('"'); - m4_output_text (context, file, strlen (file)); - OUTPUT_CHARACTER ('"'); - } - OUTPUT_CHARACTER ('\n'); - m4_set_output_line (context, line); - } - } - - /* Output the token, and track embedded newlines. */ - for (; length-- > 0; text++) - { - if (start_of_output_line) - { - start_of_output_line = false; - m4_set_output_line (context, m4_get_output_line (context) + 1); - -#ifdef DEBUG_OUTPUT - xfprintf (stderr, "DEBUG: line %d, cur %lu, cur out %lu\n", line, - (unsigned long int) m4_get_current_line (context), - (unsigned long int) m4_get_output_line (context)); -#endif - } - OUTPUT_CHARACTER (*text); - if (*text == '\n') - start_of_output_line = true; - } - } -} - -/* Format an int VAL, and stuff it into an obstack OBS. Used for - macros expanding to numbers. FIXME - support wider types, and - unsigned types. */ -void -m4_shipout_int (m4_obstack *obs, int val) -{ - /* Using obstack_printf (obs, "%d", val) has too much overhead. */ - unsigned int uval; - char buf[INT_BUFSIZE_BOUND (unsigned int)]; - char *p = buf + INT_STRLEN_BOUND (unsigned int); - - if (val < 0) - { - obstack_1grow (obs, '-'); - uval = -(unsigned int) val; - } - else - uval = val; - *p = '\0'; - do - *--p = '0' + uval % 10; - while (uval /= 10); - obstack_grow (obs, p, strlen (p)); -} - -/* Output the text S, of length LEN, to OBS. If QUOTED, also output - current quote characters around S. If LEN is SIZE_MAX, use the - string length of S instead. */ -void -m4_shipout_string (m4 *context, m4_obstack *obs, const char *s, size_t len, - bool quoted) -{ - m4_shipout_string_trunc (obs, s, len, - quoted ? m4_get_syntax_quotes (M4SYNTAX) : NULL, - NULL); -} - -/* Output the text S, of length LEN, to OBS. If QUOTES, also output - quote characters around S. If LEN is SIZE_MAX, use the string - length of S instead. If MAX_LEN, reduce *MAX_LEN by LEN. If LEN - is larger than *MAX_LEN, then truncate output and return true; - otherwise return false. Quotes do not count against MAX_LEN. */ -bool -m4_shipout_string_trunc (m4_obstack *obs, const char *s, size_t len, - const m4_string_pair *quotes, size_t *max_len) -{ - size_t max = max_len ? *max_len : SIZE_MAX; - - assert (obs && s); - if (len == SIZE_MAX) - len = strlen (s); - if (quotes) - obstack_grow (obs, quotes->str1, quotes->len1); - if (len < max) - { - obstack_grow (obs, s, len); - max -= len; - } - else - { - obstack_grow (obs, s, max); - obstack_grow (obs, "...", 3); - max = 0; - } - if (quotes) - obstack_grow (obs, quotes->str2, quotes->len2); - if (max_len) - *max_len = max; - return max == 0; -} - - - -/* --- FUNCTIONS FOR USE BY DIVERSIONS --- */ - -/* Make a file for diversion DIVNUM, and install it in the diversion table. - Grow the size of the diversion table as needed. */ - -/* The number of possible diversions is limited only by memory and - available file descriptors (each overflowing diversion uses one). */ - -void -m4_make_diversion (m4 *context, int divnum) -{ - m4_diversion *diversion = NULL; - - if (m4_get_current_diversion (context) == divnum) - return; - - if (output_diversion) - { - assert (!output_file || output_diversion->u.file == output_file); - assert (output_diversion->divnum != divnum); - if (!output_diversion->size && !output_diversion->u.file) - { - assert (!output_diversion->used); - if (!gl_oset_remove (diversion_table, output_diversion)) - assert (false); - output_diversion->u.next = free_list; - free_list = output_diversion; - } - else if (output_diversion->size) - output_diversion->used = output_diversion->size - output_unused; - else if (output_diversion->used) - { - assert (output_diversion->divnum != 0); - FILE *file = output_diversion->u.file; - output_diversion->u.file = NULL; - if (m4_tmpclose (file, output_diversion->divnum) != 0) - m4_error (context, 0, errno, NULL, - _("cannot close temporary file for diversion")); - } - output_diversion = NULL; - output_file = NULL; - output_cursor = NULL; - output_unused = 0; - } - - m4_set_current_diversion (context, divnum); - - if (divnum < 0) - return; - - if (divnum == 0) - diversion = &div0; - else - { - const void *elt; - if (gl_oset_search_atleast (diversion_table, threshold_diversion_CB, - &divnum, &elt)) - { - m4_diversion *temp = (m4_diversion *) elt; - if (temp->divnum == divnum) - diversion = temp; - } - } - if (diversion == NULL) - { - /* First time visiting this diversion. */ - if (free_list) - { - diversion = free_list; - free_list = diversion->u.next; - assert (!diversion->size && !diversion->used); - } - else - { - diversion = (m4_diversion *) obstack_alloc (&diversion_storage, - sizeof *diversion); - diversion->size = 0; - diversion->used = 0; - } - diversion->u.file = NULL; - diversion->divnum = divnum; - if (!gl_oset_add (diversion_table, diversion)) - assert (false); - } - - output_diversion = diversion; - if (output_diversion->size) - { - output_cursor = output_diversion->u.buffer + output_diversion->used; - output_unused = output_diversion->size - output_diversion->used; - } - else - { - if (!output_diversion->u.file && output_diversion->used) - output_diversion->u.file = m4_tmpopen (context, - output_diversion->divnum, - false); - output_file = output_diversion->u.file; - } - - m4_set_output_line (context, -1); -} - -/* Insert a FILE into the current output file, in the same manner - diversions are handled. If ESCAPED, ensure the output is all - ASCII. */ -static void -insert_file (m4 *context, FILE *file, bool escaped) -{ - static char buffer[COPY_BUFFER_SIZE]; - size_t length; - char *str = buffer; - bool first = true; - - assert (output_diversion); - /* Insert output by big chunks. */ - while (1) - { - length = fread (buffer, 1, sizeof buffer, file); - if (ferror (file)) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("reading inserted file")); - if (length == 0) - break; - if (escaped) - { - if (first) - first = false; - else - m4_output_text (context, "\\\n", 2); - str = quotearg_style_mem (escape_quoting_style, buffer, length); - } - m4_output_text (context, str, escaped ? strlen (str) : length); - } -} - -/* Insert a FILE into the current output file, in the same manner - diversions are handled. This allows files to be included, without - having them rescanned by m4. */ -void -m4_insert_file (m4 *context, FILE *file) -{ - /* Optimize out inserting into a sink. */ - if (output_diversion) - insert_file (context, file, false); -} - -/* Insert DIVERSION living at NODE into the current output file. The - diversion is NOT placed on the expansion obstack, because it must - not be rescanned. If ESCAPED, ensure the output is ASCII. When - the file is closed, it is deleted by the system. */ -static void -insert_diversion_helper (m4 *context, m4_diversion *diversion, bool escaped) -{ - assert (diversion->divnum > 0 - && diversion->divnum != m4_get_current_diversion (context)); - /* Effectively undivert only if an output stream is active. */ - if (output_diversion) - { - if (diversion->size) - { - if (!output_diversion->u.file) - { - /* Transferring diversion metadata is faster than - copying contents. */ - assert (!output_diversion->used && output_diversion != &div0 - && !output_file); - output_diversion->u.buffer = diversion->u.buffer; - output_diversion->size = diversion->size; - output_cursor = diversion->u.buffer + diversion->used; - output_unused = diversion->size - diversion->used; - diversion->u.buffer = NULL; - } - else - { - char *str = diversion->u.buffer; - size_t len = diversion->used; - /* Avoid double-charging the total in-memory size when - transferring from one in-memory diversion to - another. */ - total_buffer_size -= diversion->size; - if (escaped) - str = quotearg_style_mem (escape_quoting_style, str, len); - m4_output_text (context, str, escaped ? strlen (str) : len); - } - } - else if (!output_diversion->u.file) - { - /* Transferring diversion metadata is faster than copying - contents. */ - assert (!output_diversion->used && output_diversion != &div0 - && !output_file); - output_diversion->u.file = m4_tmprename (context, diversion->divnum, - output_diversion->divnum); - output_diversion->used = 1; - output_file = output_diversion->u.file; - diversion->u.file = NULL; - diversion->size = 1; - } - else - { - assert (diversion->used); - if (!diversion->u.file) - diversion->u.file = m4_tmpopen (context, diversion->divnum, true); - insert_file (context, diversion->u.file, escaped); - } - - m4_set_output_line (context, -1); - } - - /* Return all space used by the diversion. */ - if (diversion->size) - { - if (!output_diversion) - total_buffer_size -= diversion->size; - free (diversion->u.buffer); - diversion->size = 0; - } - else - { - if (diversion->u.file) - { - FILE *file = diversion->u.file; - diversion->u.file = NULL; - if (m4_tmpclose (file, diversion->divnum) != 0) - m4_error (context, 0, errno, NULL, - _("cannot clean temporary file for diversion")); - } - if (m4_tmpremove (diversion->divnum) != 0) - m4_error (context, 0, errno, NULL, - _("cannot clean temporary file for diversion")); - } - diversion->used = 0; - if (!gl_oset_remove (diversion_table, diversion)) - assert (false); - diversion->u.next = free_list; - free_list = diversion; -} - -/* Insert diversion number DIVNUM into the current output file. The - diversion is NOT placed on the expansion obstack, because it must not - be rescanned. When the file is closed, it is deleted by the system. */ -void -m4_insert_diversion (m4 *context, int divnum) -{ - const void *elt; - - /* Do not care about nonexistent diversions, and undiverting stdout - or self is a no-op. */ - if (divnum <= 0 || m4_get_current_diversion (context) == divnum) - return; - if (gl_oset_search_atleast (diversion_table, threshold_diversion_CB, - &divnum, &elt)) - { - m4_diversion *diversion = (m4_diversion *) elt; - if (diversion->divnum == divnum) - insert_diversion_helper (context, diversion, false); - } -} - -/* Get back all diversions. This is done just before exiting from main, - and from m4_undivert (), if called without arguments. */ -void -m4_undivert_all (m4 *context) -{ - int divnum = m4_get_current_diversion (context); - const void *elt; - gl_oset_iterator_t iter = gl_oset_iterator (diversion_table); - while (gl_oset_iterator_next (&iter, &elt)) - { - m4_diversion *diversion = (m4_diversion *) elt; - if (diversion->divnum != divnum) - insert_diversion_helper (context, diversion, false); - } - gl_oset_iterator_free (&iter); -} - -/* Produce all diversion information in frozen format on FILE. */ -void -m4_freeze_diversions (m4 *context, FILE *file) -{ - int saved_number; - int last_inserted; - gl_oset_iterator_t iter; - const void *elt; - - saved_number = m4_get_current_diversion (context); - last_inserted = 0; - m4_make_diversion (context, 0); - output_file = file; /* kludge in the frozen file */ - - iter = gl_oset_iterator (diversion_table); - while (gl_oset_iterator_next (&iter, &elt)) - { - m4_diversion *diversion = (m4_diversion *) elt; - if (diversion->size || diversion->used) - { - if (diversion->size) - { - assert (diversion->used == (int) diversion->used); - xfprintf (file, "D%d,%d\n", diversion->divnum, - (int) diversion->used); - } - else - { - struct stat file_stat; - assert (!diversion->u.file); - diversion->u.file = m4_tmpopen (context, diversion->divnum, - true); - if (fstat (fileno (diversion->u.file), &file_stat) < 0) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("cannot stat diversion")); - /* FIXME - support 64-bit off_t with 32-bit long, and - fix frozen file format to support 64-bit integers. - This implies fixing m4_divert_text to take off_t. */ - if (file_stat.st_size < 0 - || file_stat.st_size != (unsigned long int) file_stat.st_size) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("diversion too large")); - xfprintf (file, "%c%d,%lu\n", 'D', diversion->divnum, - (unsigned long int) file_stat.st_size); - } - - insert_diversion_helper (context, diversion, true); - putc ('\n', file); - - last_inserted = diversion->divnum; - } - } - gl_oset_iterator_free (&iter); - - /* Save the active diversion number, if not already. */ - - if (saved_number != last_inserted) - xfprintf (file, "D%d,0\n\n", saved_number); -} diff --git a/m4/path.c b/m4/path.c deleted file mode 100644 index 0c6a962d..00000000 --- a/m4/path.c +++ /dev/null @@ -1,414 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1993, 1998, 2004, 2006-2010, 2013-2014, 2017 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 . -*/ - -/* Handling of path search of included files via the builtins "include" - and "sinclude". */ - -#include - -#include -#include -#include -#include - -#include "m4private.h" - -#include "configmake.h" -#include "dirname.h" -#include "filenamecat.h" - -#if OS2 /* Any others? */ -# define TRUNCATE_FILENAME 1 -#endif - -/* Define this to see runtime debug info. Implied by DEBUG. */ -/*#define DEBUG_INCL */ - -static const char *FILE_SUFFIXES[] = { - "", - ".m4f", - ".m4", - LT_MODULE_EXT, - NULL -}; - -static const char *NO_SUFFIXES[] = { "", NULL }; - -static void search_path_add (m4__search_path_info *, const char *, bool); -static void search_path_env_init (m4__search_path_info *, char *, bool); -static void include_env_init (m4 *context); - -#ifdef DEBUG_INCL -static void include_dump (m4 *context); -#endif - - -/* - * General functions for search paths - */ - -static void -search_path_add (m4__search_path_info *info, const char *dir, bool prepend) -{ - m4__search_path *path = (m4__search_path *) xmalloc (sizeof *path); - - path->len = strlen (dir); - path->dir = xstrdup (dir); - - if (path->len > info->max_length) /* remember len of longest directory */ - info->max_length = path->len; - - if (prepend) - { - path->next = info->list; - info->list = path; - if (info->list_end == NULL) - info->list_end = path; - } - else - { - path->next = NULL; - - if (info->list_end == NULL) - info->list = path; - else - info->list_end->next = path; - info->list_end = path; - } -} - -static void -search_path_env_init (m4__search_path_info *info, char *path, bool isabs) -{ - char *path_end; - - if (info == NULL || path == NULL) - return; - - do - { - path_end = strchr (path, PATH_SEPARATOR); - if (path_end) - *path_end = '\0'; - if (!isabs || *path == '/') - search_path_add (info, path, false); - path = path_end + 1; - } - while (path_end); -} - -static void -include_env_init (m4 *context) -{ - char *m4path; - - if (m4_get_posixly_correct_opt (context)) - return; - - m4path = getenv ("M4PATH"); - if (m4path) - m4path = xstrdup (m4path); - search_path_env_init (m4__get_search_path (context), m4path, false); - free (m4path); -} - - -#if TRUNCATE_FILENAME -/* Destructively modify PATH to contain no more than 8 non-`.' - characters, optionally followed by a `.' and a filenname extension - of 3 characters or fewer. */ -static char * -path_truncate (char *path) -{ - char *p, *beg = path; /* following final '/' */ - for (p = path; *p != '\0'; ++p) - { - if (ISSLASH (*p)) - beg = 1+ p; - } - - char *end = strchr (beg, '.'); /* first period */ - char *ext = strrchr (beg, '.'); /* last period */ - - size_t len = (size_t) (end - beg); /* length of filename element */ - if (len > 8) - end = beg + 8; - - if (ext == NULL) - { - *end = '\0'; - } - else if (ext != end) - { - stpncpy (end, ext, 4); - } - - return path; -} -#endif - - - -/* Functions for normal input path search */ - -void -m4_add_include_directory (m4 *context, const char *dir, bool prepend) -{ - if (m4_get_posixly_correct_opt (context)) - return; - - search_path_add (m4__get_search_path (context), dir, prepend); - -#ifdef DEBUG_INCL - xfprintf (stderr, "add_include_directory (%s) %s;\n", dir, - prepend ? "prepend" : "append"); -#endif -} - - -/* Search for FILENAME according to -B options, `.', -I options, then - M4PATH environment. If successful, return the open file, and if - RESULT is not NULL, set *RESULT to a malloc'd string that - represents the file found with respect to the current working - directory. Otherwise, return NULL, and errno reflects the failure - from searching `.' (regardless of what else was searched). */ -char * -m4_path_search (m4 *context, const char *filename, const char **suffixes) -{ - m4__search_path *incl; - char *filepath; /* buffer for constructed name */ - size_t max_suffix_len = 0; - int i, e = 0; - - /* Reject empty file. */ - if (*filename == '\0') - { - errno = ENOENT; - return NULL; - } - - /* Use no suffixes by default. */ - if (suffixes == NULL) - suffixes = NO_SUFFIXES; - - /* Find the longest suffix, so that we will always allocate enough - memory for a filename with suffix. */ - for (i = 0; suffixes && suffixes[i]; ++i) - { - size_t len = strlen (suffixes[i]); - if (len > max_suffix_len) - max_suffix_len = len; - } - - /* If file is absolute, or if we are not searching a path, a single - lookup will do the trick. */ - if (IS_ABSOLUTE_FILE_NAME (filename)) - { - size_t mem = strlen (filename); - - /* Try appending each of the suffixes we were given. */ - filepath = strncpy (xmalloc (mem + max_suffix_len +1), filename, mem +1); -#if TRUNCATE_FILENAME - filepath = path_truncate (filepath); - mem = strlen (filepath); /* recalculate length after truncation */ -#endif - for (i = 0; suffixes && suffixes[i]; ++i) - { - strcpy (filepath + mem, suffixes[i]); - if (access (filepath, R_OK) == 0) - return filepath; - - /* If search fails, we'll use the error we got from the first - access (usually with no suffix). */ - if (i == 0) - e = errno; - } - free (filepath); - - /* No such file. */ - errno = e; - return NULL; - } - - for (incl = m4__get_search_path (context)->list; - incl != NULL; incl = incl->next) - { - char *pathname = file_name_concat (incl->dir, filename, NULL); - size_t mem = strlen (pathname); - -#ifdef DEBUG_INCL - xfprintf (stderr, "path_search (%s) -- trying %s\n", filename, pathname); -#endif - - if (access (pathname, R_OK) == 0) - { - m4_debug_message (context, M4_DEBUG_TRACE_PATH, - _("path search for %s found %s"), - quotearg_style (locale_quoting_style, filename), - quotearg_n_style (1, locale_quoting_style, pathname)); - return pathname; - } - else if (!incl->len) - /* Capture errno only when searching `.'. */ - e = errno; - - filepath = strncpy (xmalloc (mem + max_suffix_len +1), pathname, mem +1); - free (pathname); -#if TRUNCATE_FILENAME - filepath = path_truncate (filepath); - mem = strlen (filepath); /* recalculate length after truncation */ -#endif - - for (i = 0; suffixes && suffixes[i]; ++i) - { - strcpy (filepath + mem, suffixes[i]); - if (access (filepath, R_OK) == 0) - return filepath; - } - free (filepath); - } - - errno = e; - return NULL; -} - - -/* Attempt to open FILE; if it opens, verify that it is not a - directory, and ensure it does not leak across execs. */ -FILE * -m4_fopen (m4 *context, const char *file, const char *mode) -{ - FILE *fp = NULL; - - if (file) - { - struct stat st; - int fd; - - fp = fopen (file, mode); - fd = fileno (fp); - - if (fstat (fd, &st) == 0 && S_ISDIR (st.st_mode)) - { - fclose (fp); - errno = EISDIR; - return NULL; - } - if (set_cloexec_flag (fileno (fp), true) != 0) - m4_error (context, 0, errno, NULL, - _("cannot protect input file across forks")); - } - return fp; -} - - -/* Generic load function. Push the input file or load the module named - FILENAME, if it can be found in the search path. Complain - about inaccesible files iff SILENT is false. */ -bool -m4_load_filename (m4 *context, const m4_call_info *caller, - const char *filename, m4_obstack *obs, bool silent) -{ - char *filepath = NULL; - char *suffix = NULL; - bool new_input = false; - - if (m4_get_posixly_correct_opt (context)) - { - if (access (filename, R_OK) == 0) - filepath = xstrdup (filename); - } - else - filepath = m4_path_search (context, filename, FILE_SUFFIXES); - - if (filepath) - suffix = strrchr (filepath, '.'); - - if (!m4_get_posixly_correct_opt (context) - && suffix - && STREQ (suffix, LT_MODULE_EXT)) - { - m4_module_load (context, filename, obs); - } - else - { - FILE *fp = NULL; - - if (filepath) - fp = m4_fopen (context, filepath, "r"); - - if (fp == NULL) - { - if (!silent) - m4_error (context, 0, errno, caller, _("cannot open file '%s'"), - filename); - free (filepath); - return false; - } - - m4_push_file (context, fp, filepath, true); - new_input = true; - } - free (filepath); - - return new_input; -} - - -void -m4__include_init (m4 *context) -{ - include_env_init (context); - - { - m4__search_path_info *info = m4__get_search_path (context); - - /* If M4PATH was not set, then search just the current directory by - default. */ - assert (info); - if (info->list_end == NULL) - search_path_add (info, "", false); - - /* Non-core modules installation directory. */ - search_path_add (info, PKGLIBDIR, false); - } - -#ifdef DEBUG_INCL - fputs ("initial include search path...\n", stderr); - include_dump (context); -#endif -} - - - -#ifdef DEBUG_INCL - -static void -include_dump (m4 *context) -{ - m4__search_path *incl; - - fputs ("include_dump:\n", stderr); - for (incl = m4__get_search_path (context)->list; - incl != NULL; incl = incl->next) - xfprintf (stderr, "\t'%s'\n", incl->dir); -} - -#endif /* DEBUG_INCL */ diff --git a/m4/resyntax.c b/m4/resyntax.c deleted file mode 100644 index 704e357c..00000000 --- a/m4/resyntax.c +++ /dev/null @@ -1,127 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 2006-2008, 2010, 2013-2014, 2017 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 . -*/ - -#include - -#include -#include - -#include "m4private.h" - -typedef struct { - const char *spec; - const int code; -} m4_resyntax; - -/* The syntaxes named in this table are saved into frozen files. Changing - the mappings will break programs that load a frozen file made before - such a change... */ - -static m4_resyntax const m4_resyntax_map[] = -{ - /* First, the canonical definitions for reverse lookups: */ - - { "AWK", RE_SYNTAX_AWK }, - { "ED", RE_SYNTAX_ED }, - { "EGREP", RE_SYNTAX_EGREP }, - { "EMACS", RE_SYNTAX_EMACS }, - { "GNU_AWK", RE_SYNTAX_GNU_AWK }, - { "GREP", RE_SYNTAX_GREP }, - { "POSIX_AWK", RE_SYNTAX_POSIX_AWK }, - { "POSIX_BASIC", RE_SYNTAX_POSIX_BASIC }, - { "POSIX_EGREP", RE_SYNTAX_POSIX_EGREP }, - { "POSIX_EXTENDED", RE_SYNTAX_POSIX_EXTENDED }, - { "POSIX_MINIMAL_BASIC", RE_SYNTAX_POSIX_MINIMAL_BASIC }, - { "SED", RE_SYNTAX_SED }, - - /* The rest are aliases, for forward lookups only: */ - - { "", RE_SYNTAX_EMACS }, - { "BASIC", RE_SYNTAX_POSIX_BASIC }, - { "BSD_M4", RE_SYNTAX_POSIX_EXTENDED }, - { "EXTENDED", RE_SYNTAX_POSIX_EXTENDED }, - { "GAWK", RE_SYNTAX_GNU_AWK }, - { "GNU_EGREP", RE_SYNTAX_EGREP }, - { "GNU_EMACS", RE_SYNTAX_EMACS }, - { "GNU_M4", RE_SYNTAX_EMACS }, - { "MINIMAL", RE_SYNTAX_POSIX_MINIMAL_BASIC }, - { "MINIMAL_BASIC", RE_SYNTAX_POSIX_MINIMAL_BASIC }, - { "POSIX_MINIMAL", RE_SYNTAX_POSIX_MINIMAL_BASIC }, - - /* End marker: */ - - { NULL, -1 } -}; - - -/* Return the internal code representing the syntax SPEC, or -1 if - SPEC is invalid. The `m4_syntax_map' table is searched case - insensitively, after replacing any spaces or dashes in SPEC with - underscore characters. Possible matches for the "GNU_M4" element - then, are "gnu m4", "GNU-m4" or "Gnu_M4". */ -int -m4_regexp_syntax_encode (const char *spec) -{ - const m4_resyntax *resyntax; - char *canonical; - char *p; - - /* Unless specified otherwise, return the historical GNU M4 default. */ - if (!spec) - return RE_SYNTAX_EMACS; - - canonical = xstrdup (spec); - - /* Canonicalise SPEC. */ - for (p = canonical; *p != '\0'; ++p) - { - if ((*p == ' ') || (*p == '-')) - *p = '_'; - else if (islower (to_uchar (*p))) - *p = toupper (to_uchar (*p)); - } - - for (resyntax = m4_resyntax_map; resyntax->spec != NULL; ++resyntax) - { - if (STREQ (resyntax->spec, canonical)) - break; - } - - free (canonical); - - return resyntax->code; -} - - -/* Return the syntax specifier that matches CODE, or NULL if there is - no match. */ -const char * -m4_regexp_syntax_decode (int code) -{ - const m4_resyntax *resyntax; - - for (resyntax = m4_resyntax_map; resyntax->spec != NULL; ++resyntax) - { - if (resyntax->code == code) - break; - } - - return resyntax->spec; -} diff --git a/m4/symtab.c b/m4/symtab.c deleted file mode 100644 index b04b55e7..00000000 --- a/m4/symtab.c +++ /dev/null @@ -1,968 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 2001, 2005-2008, 2010, 2013-2014, 2017 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 . -*/ - -#include - -#include "m4private.h" - -/* Define this to see runtime debug info. Implied by DEBUG. */ -/*#define DEBUG_SYM */ - -/* This file handles all the low level work around the symbol table. The - symbol table is an abstract hash table type implemented in hash.c. Each - symbol is represented by `struct m4_symbol', which is stored in the hash - table keyed by the symbol name. As a special case, to facilitate the - "pushdef" and "popdef" builtins, the value stored against each key is a - stack of `m4_symbol_value'. All the value entries for a symbol name are - simply ordered on the stack by age. The most recently pushed definition - will then always be the first found. - - Also worthy of mention is the way traced symbols are managed: the - trace bit is associated with a particular symbol name. If a symbol - is undefined and then redefined, it does not lose its trace bit. - This is achieved by not removing traced symbol names from the - symbol table, even if their value stack is empty. That way, when - the name is given a new value, it is pushed onto the empty stack, - and the trace bit attached to the name was never lost. There is a - small amount of fluff in these functions to make sure that such - symbols (with empty value stacks) are invisible to the users of - this module. */ - -#define M4_SYMTAB_DEFAULT_SIZE 2047 - -struct m4_symbol_table { - m4_hash *table; -}; - -static m4_symbol *symtab_fetch (m4_symbol_table*, const char *, - size_t); -static void symbol_popval (m4_symbol *); -static void * symbol_destroy_CB (m4_symbol_table *, const char *, - size_t, m4_symbol *, void *); -static void * arg_destroy_CB (m4_hash *, const void *, void *, - void *); -static void * arg_copy_CB (m4_hash *, const void *, void *, - m4_hash *); - - -/* -- SYMBOL TABLE MANAGEMENT -- - - These functions are used to manage a symbol table as a whole. */ - -m4_symbol_table * -m4_symtab_create (size_t size) -{ - m4_symbol_table *symtab = (m4_symbol_table *) xmalloc (sizeof *symtab); - - symtab->table = m4_hash_new (size ? size : M4_SYMTAB_DEFAULT_SIZE, - m4_hash_string_hash, m4_hash_string_cmp); - return symtab; -} - -void -m4_symtab_delete (m4_symbol_table *symtab) -{ - assert (symtab); - assert (symtab->table); - - m4_symtab_apply (symtab, true, symbol_destroy_CB, NULL); - m4_hash_delete (symtab->table); - free (symtab); -} - -/* For every symbol in SYMTAB, execute the callback FUNC with the name - and value of the symbol being visited, and the opaque parameter - USERDATA. Skip undefined symbols that are placeholders for - traceon, unless INCLUDE_TRACE is true. If FUNC returns non-NULL, - abort the iteration and return the same result; otherwise return - NULL when iteration completes. */ -void * -m4_symtab_apply (m4_symbol_table *symtab, bool include_trace, - m4_symtab_apply_func *func, void *userdata) -{ - m4_hash_iterator *place = NULL; - void * result = NULL; - - assert (symtab); - assert (symtab->table); - assert (func); - - while ((place = m4_get_hash_iterator_next (symtab->table, place))) - { - m4_symbol *symbol = m4_get_hash_iterator_value (place); - if (symbol->value || include_trace) - { - const m4_string *key - = (const m4_string *) m4_get_hash_iterator_key (place); - result = func (symtab, key->str, key->len, symbol, userdata); - } - if (result != NULL) - { - m4_free_hash_iterator (symtab->table, place); - break; - } - } - - return result; -} - -/* Ensure that NAME of length LEN exists in the table, creating an - entry if needed. */ -static m4_symbol * -symtab_fetch (m4_symbol_table *symtab, const char *name, size_t len) -{ - m4_symbol **psymbol; - m4_symbol *symbol; - m4_string key; - - assert (symtab); - assert (name); - - /* Safe to cast away const, since m4_hash_lookup doesn't modify - key. */ - key.str = (char *) name; - key.len = len; - psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, &key); - if (psymbol) - { - symbol = *psymbol; - } - else - { - /* Use xmemdup0 rather than memdup so that debugging the symbol - table is easier. */ - m4_string *new_key = (m4_string *) xmalloc (sizeof *new_key); - new_key->str = xmemdup0 (name, len); - new_key->len = len; - symbol = (m4_symbol *) xzalloc (sizeof *symbol); - m4_hash_insert (symtab->table, new_key, symbol); - } - - return symbol; -} - -/* Remove every symbol that references the given module from - the symbol table. */ -void -m4__symtab_remove_module_references (m4_symbol_table *symtab, - m4_module *module) -{ - m4_hash_iterator *place = 0; - - assert (module); - - /* Traverse each symbol name in the hash table. */ - while ((place = m4_get_hash_iterator_next (symtab->table, place))) - { - m4_symbol *symbol = (m4_symbol *) m4_get_hash_iterator_value (place); - m4_symbol_value *data = m4_get_symbol_value (symbol); - - /* For symbols that have token data... */ - if (data) - { - /* Purge any shadowed references. */ - while (VALUE_NEXT (data)) - { - m4_symbol_value *next = VALUE_NEXT (data); - - if (VALUE_MODULE (next) == module) - { - VALUE_NEXT (data) = VALUE_NEXT (next); - - assert (next->type != M4_SYMBOL_PLACEHOLDER); - m4_symbol_value_delete (next); - } - else - data = next; - } - - /* Purge the live reference if necessary. */ - if (SYMBOL_MODULE (symbol) == module) - { - const m4_string *key - = (const m4_string *) m4_get_hash_iterator_key (place); - m4_symbol_popdef (symtab, key->str, key->len); - } - } - } -} - - -/* This callback is used exclusively by m4_symtab_delete(), to cleanup - the memory used by the symbol table. As such, the trace bit is reset - on every symbol so that m4_symbol_popdef() doesn't try to preserve - the table entry. */ -static void * -symbol_destroy_CB (m4_symbol_table *symtab, const char *name, size_t len, - m4_symbol *symbol, void *ignored M4_GNUC_UNUSED) -{ - m4_string key; - key.str = xmemdup0 (name, len); - key.len = len; - - symbol->traced = false; - - while (m4_hash_lookup (symtab->table, &key)) - m4_symbol_popdef (symtab, key.str, key.len); - - free (key.str); - - return NULL; -} - - - -/* -- SYMBOL MANAGEMENT -- - - The following functions manipulate individual symbols within - an existing table. */ - -/* Return the symbol associated to NAME of length LEN, or else - NULL. */ -m4_symbol * -m4_symbol_lookup (m4_symbol_table *symtab, const char *name, size_t len) -{ - m4_string key; - m4_symbol **psymbol; - - /* Safe to cast away const, since m4_hash_lookup doesn't modify - key. */ - key.str = (char *) name; - key.len = len; - psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, &key); - - /* If just searching, return status of search -- if only an empty - struct is returned, that is treated as a failed lookup. */ - return (psymbol && m4_get_symbol_value (*psymbol)) ? *psymbol : NULL; -} - - -/* Insert NAME of length LEN into the symbol table. If there is - already a symbol associated with NAME, push the new VALUE on top of - the value stack for this symbol. Otherwise create a new - association. */ -m4_symbol * -m4_symbol_pushdef (m4_symbol_table *symtab, const char *name, size_t len, - m4_symbol_value *value) -{ - m4_symbol *symbol; - - assert (symtab); - assert (name); - assert (value); - - symbol = symtab_fetch (symtab, name, len); - VALUE_NEXT (value) = m4_get_symbol_value (symbol); - symbol->value = value; - - assert (m4_get_symbol_value (symbol)); - - return symbol; -} - -/* Return the symbol associated with NAME of length LEN in the symbol - table, creating a new symbol if necessary. In either case set the - symbol's VALUE. */ -m4_symbol * -m4_symbol_define (m4_symbol_table *symtab, const char *name, size_t len, - m4_symbol_value *value) -{ - m4_symbol *symbol; - - assert (symtab); - assert (name); - assert (value); - - symbol = symtab_fetch (symtab, name, len); - if (m4_get_symbol_value (symbol)) - symbol_popval (symbol); - - VALUE_NEXT (value) = m4_get_symbol_value (symbol); - symbol->value = value; - - assert (m4_get_symbol_value (symbol)); - - return symbol; -} - -/* Pop the topmost value stack entry from the symbol associated with - NAME of length LEN, deleting it from the table entirely if that was - the last remaining value in the stack. */ -void -m4_symbol_popdef (m4_symbol_table *symtab, const char *name, size_t len) -{ - m4_string key; - m4_symbol **psymbol; - - /* Safe to cast away const, since m4_hash_lookup doesn't modify - key. */ - key.str = (char *) name; - key.len = len; - psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, &key); - - assert (psymbol); - assert (*psymbol); - - symbol_popval (*psymbol); - - /* Only remove the hash table entry if the last value in the - symbol value stack was successfully removed. */ - if (!m4_get_symbol_value (*psymbol) && !m4_get_symbol_traced (*psymbol)) - { - m4_string *old_key; - DELETE (*psymbol); - old_key = (m4_string *) m4_hash_remove (symtab->table, &key); - free (old_key->str); - free (old_key); - } -} - -/* Remove the top-most value from SYMBOL's stack. */ -static void -symbol_popval (m4_symbol *symbol) -{ - m4_symbol_value *stale; - - assert (symbol); - - stale = m4_get_symbol_value (symbol); - - if (stale) - { - symbol->value = VALUE_NEXT (stale); - m4_symbol_value_delete (stale); - } -} - -/* Create a new symbol value, with fields populated for default - behavior. */ -m4_symbol_value * -m4_symbol_value_create (void) -{ - m4_symbol_value *value = (m4_symbol_value *) xzalloc (sizeof *value); - VALUE_MAX_ARGS (value) = SIZE_MAX; - return value; -} - -/* Remove VALUE from the symbol table, and mark it as deleted. If no - expansions are pending, reclaim its resources. */ -void -m4_symbol_value_delete (m4_symbol_value *value) -{ - if (VALUE_PENDING (value) > 0) - BIT_SET (VALUE_FLAGS (value), VALUE_DELETED_BIT); - else - { - if (VALUE_ARG_SIGNATURE (value)) - { - m4_hash_apply (VALUE_ARG_SIGNATURE (value), arg_destroy_CB, NULL); - m4_hash_delete (VALUE_ARG_SIGNATURE (value)); - } - switch (value->type) - { - case M4_SYMBOL_TEXT: - DELETE (value->u.u_t.text); - break; - case M4_SYMBOL_PLACEHOLDER: - DELETE (value->u.u_t.text); - break; - case M4_SYMBOL_VOID: - case M4_SYMBOL_FUNC: - break; - default: - assert (!"m4_symbol_value_delete"); - abort (); - } - free (value); - } -} - -/* Rename the entire stack of values associated with NAME and LEN1 to - NEWNAME and LEN2. */ -m4_symbol * -m4_symbol_rename (m4_symbol_table *symtab, const char *name, size_t len1, - const char *newname, size_t len2) -{ - m4_symbol *symbol = NULL; - m4_symbol **psymbol; - m4_string key; - m4_string *pkey; - - assert (symtab); - assert (name); - assert (newname); - - /* Safe to cast away const, since m4_hash_lookup doesn't modify - key. */ - key.str = (char *) name; - key.len = len1; - /* Use a low level hash fetch, so we can save the symbol value when - removing the symbol name from the symbol table. */ - psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, &key); - - if (psymbol) - { - symbol = *psymbol; - - /* Remove the old name from the symbol table. */ - pkey = (m4_string *) m4_hash_remove (symtab->table, &key); - assert (pkey && !m4_hash_lookup (symtab->table, &key)); - free (pkey->str); - - pkey->str = xmemdup0 (newname, len2); - pkey->len = len2; - m4_hash_insert (symtab->table, pkey, *psymbol); - } - /* else - NAME does not name a symbol in symtab->table! */ - - return symbol; -} - - -/* Callback used by m4_symbol_popdef () to release the memory used - by values in the arg_signature hash. */ -static void * -arg_destroy_CB (m4_hash *hash, const void *name, void *arg, void *ignored) -{ - struct m4_symbol_arg *token_arg = (struct m4_symbol_arg *) arg; - - assert (name); - assert (hash); - - if (SYMBOL_ARG_DEFAULT (token_arg)) - DELETE (SYMBOL_ARG_DEFAULT (token_arg)); - free (token_arg); - free (m4_hash_remove (hash, (const char *) name)); - - return NULL; -} - -/* Copy the symbol SRC into DEST. Return true if builtin tokens were - flattened. */ -bool -m4_symbol_value_copy (m4 *context, m4_symbol_value *dest, m4_symbol_value *src) -{ - m4_symbol_value *next; - bool result = false; - - assert (dest); - assert (src); - - switch (dest->type) - { - case M4_SYMBOL_TEXT: - DELETE (dest->u.u_t.text); - break; - case M4_SYMBOL_PLACEHOLDER: - DELETE (dest->u.u_t.text); - break; - case M4_SYMBOL_VOID: - case M4_SYMBOL_FUNC: - break; - default: - assert (!"m4_symbol_value_delete"); - abort (); - } - - if (VALUE_ARG_SIGNATURE (dest)) - { - m4_hash_apply (VALUE_ARG_SIGNATURE (dest), arg_destroy_CB, NULL); - m4_hash_delete (VALUE_ARG_SIGNATURE (dest)); - } - - /* Copy the value contents over, being careful to preserve - the next pointer. */ - next = VALUE_NEXT (dest); - memcpy (dest, src, sizeof (m4_symbol_value)); - VALUE_NEXT (dest) = next; - - /* Caller is supposed to free text token strings, so we have to - copy the string not just its address in that case. */ - switch (src->type) - { - case M4_SYMBOL_TEXT: - { - size_t len = m4_get_symbol_value_len (src); - unsigned int age = m4_get_symbol_value_quote_age (src); - m4_set_symbol_value_text (dest, - xmemdup0 (m4_get_symbol_value_text (src), - len), len, age); - } - break; - case M4_SYMBOL_FUNC: - m4__set_symbol_value_builtin (dest, src->u.builtin); - break; - case M4_SYMBOL_PLACEHOLDER: - m4_set_symbol_value_placeholder (dest, - xstrdup (m4_get_symbol_value_placeholder - (src))); - break; - case M4_SYMBOL_COMP: - { - m4__symbol_chain *chain = src->u.u_c.chain; - size_t len; - char *str; - const m4_string_pair *quotes; - m4_obstack *obs = m4_arg_scratch (context); - while (chain) - { - switch (chain->type) - { - case M4__CHAIN_STR: - obstack_grow (obs, chain->u.u_s.str, chain->u.u_s.len); - break; - case M4__CHAIN_FUNC: - result = true; - break; - case M4__CHAIN_ARGV: - quotes = m4__quote_cache (M4SYNTAX, NULL, chain->quote_age, - chain->u.u_a.quotes); - if (chain->u.u_a.has_func && !chain->u.u_a.flatten) - result = true; - m4__arg_print (context, obs, chain->u.u_a.argv, - chain->u.u_a.index, quotes, true, NULL, NULL, - NULL, false, false); - break; - default: - assert (!"m4_symbol_value_copy"); - abort (); - } - chain = chain->next; - } - obstack_1grow (obs, '\0'); - len = obstack_object_size (obs); - str = xcharalloc (len); - memcpy (str, obstack_finish (obs), len); - m4_set_symbol_value_text (dest, str, len - 1, 0); - } - break; - default: - assert (!"m4_symbol_value_copy"); - abort (); - } - if (VALUE_ARG_SIGNATURE (src)) - VALUE_ARG_SIGNATURE (dest) = m4_hash_dup (VALUE_ARG_SIGNATURE (src), - arg_copy_CB); - return result; -} - -static void * -arg_copy_CB (m4_hash *src, const void *name, void *arg, m4_hash *dest) -{ - m4_hash_insert ((m4_hash *) dest, name, arg); - return NULL; -} - -/* Set the tracing status of the symbol NAME of length LEN to TRACED. - This takes a name, rather than a symbol, since we hide macros that - are traced but otherwise undefined from normal lookups, but still - can affect their tracing status. Return true iff the macro was - previously traced. */ -bool -m4_set_symbol_name_traced (m4_symbol_table *symtab, const char *name, - size_t len, bool traced) -{ - m4_symbol *symbol; - bool result; - - assert (symtab); - assert (name); - - if (traced) - symbol = symtab_fetch (symtab, name, len); - else - { - m4_string key; - m4_symbol **psymbol; - - /* Safe to cast away const, since m4_hash_lookup doesn't modify - key. */ - key.str = (char *) name; - key.len = len; - psymbol = (m4_symbol **) m4_hash_lookup (symtab->table, &key); - if (!psymbol) - return false; - symbol = *psymbol; - } - - result = symbol->traced; - symbol->traced = traced; - if (!traced && !m4_get_symbol_value (symbol)) - { - /* Free an undefined entry once it is no longer traced. */ - m4_string key; - m4_string *old_key; - assert (result); - free (symbol); - - /* Safe to cast away const, since m4_hash_lookup doesn't modify - key. */ - key.str = (char *) name; - key.len = len; - old_key = (m4_string *) m4_hash_remove (symtab->table, &key); - free (old_key->str); - free (old_key); - } - - return result; -} - -/* Grow OBS with a text representation of VALUE. If QUOTES, then use - it to surround a text definition. If FLATTEN, builtins are - converted to empty quotes; if CHAINP, *CHAINP is updated with macro - tokens; otherwise, builtins are represented by their name. If - MAXLEN, then truncate text definitions to *MAXLEN, and adjust by - how many characters are printed. If MODULE, then include which - module defined a builtin. Return true if the output was truncated. - QUOTES and MODULE do not count against the truncation length. */ -bool -m4__symbol_value_print (m4 *context, m4_symbol_value *value, m4_obstack *obs, - const m4_string_pair *quotes, bool flatten, - m4__symbol_chain **chainp, size_t *maxlen, bool module) -{ - const char *text; - m4__symbol_chain *chain; - size_t len = maxlen ? *maxlen : SIZE_MAX; - bool result = false; - - switch (value->type) - { - case M4_SYMBOL_TEXT: - if (m4_shipout_string_trunc (obs, m4_get_symbol_value_text (value), - m4_get_symbol_value_len (value), quotes, - &len)) - result = true; - break; - case M4_SYMBOL_FUNC: - m4__builtin_print (obs, value->u.builtin, flatten, chainp, quotes, - module); - module = false; - break; - case M4_SYMBOL_PLACEHOLDER: - if (flatten) - { - if (quotes) - { - obstack_grow (obs, quotes->str1, quotes->len1); - obstack_grow (obs, quotes->str2, quotes->len2); - } - module = false; - } - else - { - text = m4_get_symbol_value_placeholder (value); - obstack_1grow (obs, '<'); - obstack_1grow (obs, '<'); - obstack_grow (obs, text, strlen (text)); - obstack_1grow (obs, '>'); - obstack_1grow (obs, '>'); - } - break; - case M4_SYMBOL_COMP: - chain = value->u.u_c.chain; - assert (!module); - if (quotes) - obstack_grow (obs, quotes->str1, quotes->len1); - while (chain && !result) - { - switch (chain->type) - { - case M4__CHAIN_STR: - if (m4_shipout_string_trunc (obs, chain->u.u_s.str, - chain->u.u_s.len, NULL, &len)) - result = true; - break; - case M4__CHAIN_FUNC: - m4__builtin_print (obs, chain->u.builtin, flatten, chainp, - quotes, module); - break; - case M4__CHAIN_ARGV: - if (m4__arg_print (context, obs, chain->u.u_a.argv, - chain->u.u_a.index, - m4__quote_cache (M4SYNTAX, NULL, - chain->quote_age, - chain->u.u_a.quotes), - chain->u.u_a.flatten, chainp, NULL, &len, - false, module)) - result = true; - break; - default: - assert (!"m4__symbol_value_print"); - abort (); - } - chain = chain->next; - } - if (quotes) - obstack_grow (obs, quotes->str2, quotes->len2); - break; - default: - assert (!"m4__symbol_value_print"); - abort (); - } - - if (module && VALUE_MODULE (value)) - { - obstack_1grow (obs, '{'); - text = m4_get_module_name (VALUE_MODULE (value)); - obstack_grow (obs, text, strlen (text)); - obstack_1grow (obs, '}'); - } - if (maxlen) - *maxlen = len; - return result; -} - -/* Grow OBS with a text representation of SYMBOL. If QUOTES, then use - it to surround each text definition. If STACK, then append all - pushdef'd values, rather than just the top. If ARG_LENGTH is less - than SIZE_MAX, then truncate text definitions to that length. If - MODULE, then include which module defined a builtin. QUOTES and - MODULE do not count toward truncation. */ -void -m4_symbol_print (m4 *context, m4_symbol *symbol, m4_obstack *obs, - const m4_string_pair *quotes, bool stack, size_t arg_length, - bool module) -{ - m4_symbol_value *value; - size_t len = arg_length; - - assert (symbol); - assert (obs); - - value = m4_get_symbol_value (symbol); - m4__symbol_value_print (context, value, obs, quotes, false, NULL, &len, - module); - if (stack) - { - value = VALUE_NEXT (value); - while (value) - { - obstack_1grow (obs, ','); - obstack_1grow (obs, ' '); - len = arg_length; - m4__symbol_value_print (context, value, obs, quotes, false, NULL, - &len, module); - value = VALUE_NEXT (value); - } - } -} - - -/* Define these functions at the end, so that calls in the file use the - faster macro version from m4module.h. */ - -/* Pop all values from the symbol associated with NAME. */ -#undef m4_symbol_delete -void -m4_symbol_delete (m4_symbol_table *symtab, const char *name, size_t len) -{ - while (m4_symbol_lookup (symtab, name, len)) - m4_symbol_popdef (symtab, name, len); -} - -#undef m4_get_symbol_traced -bool -m4_get_symbol_traced (m4_symbol *symbol) -{ - assert (symbol); - return symbol->traced; -} - -#undef m4_symbol_value_flatten_args -bool -m4_symbol_value_flatten_args (m4_symbol_value *value) -{ - assert (value); - return BIT_TEST (value->flags, VALUE_FLATTEN_ARGS_BIT); -} - -#undef m4_get_symbol_value -m4_symbol_value * -m4_get_symbol_value (m4_symbol *symbol) -{ - assert (symbol); - return symbol->value; -} - -#undef m4_is_symbol_value_text -bool -m4_is_symbol_value_text (m4_symbol_value *value) -{ - assert (value); - return (value->type == M4_SYMBOL_TEXT); -} - -#undef m4_is_symbol_value_func -bool -m4_is_symbol_value_func (m4_symbol_value *value) -{ - assert (value); - return (value->type == M4_SYMBOL_FUNC); -} - -#undef m4_is_symbol_value_placeholder -bool -m4_is_symbol_value_placeholder (m4_symbol_value *value) -{ - assert (value); - return (value->type == M4_SYMBOL_PLACEHOLDER); -} - -#undef m4_is_symbol_value_void -bool -m4_is_symbol_value_void (m4_symbol_value *value) -{ - assert (value); - return (value->type == M4_SYMBOL_VOID); -} - -#undef m4_get_symbol_value_text -const char * -m4_get_symbol_value_text (m4_symbol_value *value) -{ - assert (value && value->type == M4_SYMBOL_TEXT); - return value->u.u_t.text; -} - -#undef m4_get_symbol_value_len -size_t -m4_get_symbol_value_len (m4_symbol_value *value) -{ - assert (value && value->type == M4_SYMBOL_TEXT); - return value->u.u_t.len; -} - -#undef m4_get_symbol_value_quote_age -unsigned int -m4_get_symbol_value_quote_age (m4_symbol_value *value) -{ - assert (value && value->type == M4_SYMBOL_TEXT); - return value->u.u_t.quote_age; -} - -#undef m4_get_symbol_value_func -m4_builtin_func * -m4_get_symbol_value_func (m4_symbol_value *value) -{ - assert (value && value->type == M4_SYMBOL_FUNC); - return value->u.builtin->builtin.func; -} - -#undef m4_get_symbol_value_builtin -const m4_builtin * -m4_get_symbol_value_builtin (m4_symbol_value *value) -{ - assert (value && value->type == M4_SYMBOL_FUNC); - return &value->u.builtin->builtin; -} - -#undef m4_get_symbol_value_placeholder -const char * -m4_get_symbol_value_placeholder (m4_symbol_value *value) -{ - assert (value && value->type == M4_SYMBOL_PLACEHOLDER); - return value->u.u_t.text; -} - -#undef m4_set_symbol_value_text -void -m4_set_symbol_value_text (m4_symbol_value *value, const char *text, size_t len, - unsigned int quote_age) -{ - assert (value && text); - /* In practice, it is easier to debug when we guarantee a - terminating NUL, even when there are embedded NULs. */ - assert (!text[len]); - - value->type = M4_SYMBOL_TEXT; - value->u.u_t.text = text; - value->u.u_t.len = len; - value->u.u_t.quote_age = quote_age; -} - -#undef m4__set_symbol_value_builtin -void -m4__set_symbol_value_builtin (m4_symbol_value *value, - const m4__builtin *builtin) -{ - assert (value && builtin); - - value->type = M4_SYMBOL_FUNC; - value->u.builtin = builtin; - VALUE_MODULE (value) = builtin->module; - VALUE_FLAGS (value) = builtin->builtin.flags; - VALUE_MIN_ARGS (value) = builtin->builtin.min_args; - VALUE_MAX_ARGS (value) = builtin->builtin.max_args; -} - -#undef m4_set_symbol_value_placeholder -void -m4_set_symbol_value_placeholder (m4_symbol_value *value, const char *text) -{ - assert (value); - assert (text); - - value->type = M4_SYMBOL_PLACEHOLDER; - value->u.u_t.text = text; - value->u.u_t.len = SIZE_MAX; /* len is not tracked for placeholders. */ -} - - -#ifdef DEBUG_SYM - -static void *dump_symbol_CB (m4_symbol_table *symtab, const char *name, - m4_symbol *symbol, void *userdata); -static M4_GNUC_UNUSED void * -symtab_dump (m4 *context, m4_symbol_table *symtab) -{ - return m4_symtab_apply (symtab, true, dump_symbol_CB, context); -} - -static void * -dump_symbol_CB (m4_symbol_table *symtab, const char *name, - m4_symbol *symbol, void *ptr) -{ - m4 * context = (m4 *) ptr; - m4_symbol_value *value = m4_get_symbol_value (symbol); - int flags = value ? SYMBOL_FLAGS (symbol) : 0; - m4_module * module = value ? SYMBOL_MODULE (symbol) : NULL; - const char * module_name = module ? m4_get_module_name (module) : "NONE"; - - xfprintf (stderr, "%10s: (%d%s) %s=", module_name, flags, - m4_get_symbol_traced (symbol) ? "!" : "", name); - - if (!value) - fputs ("", stderr); - else if (m4_is_symbol_value_void (value)) - fputs ("", stderr); - else - { - m4_obstack obs; - obstack_init (&obs); - m4__symbol_value_print (context, value, &obs, NULL, false, NULL, NULL, - true); - xfprintf (stderr, "%s", (char *) obstack_finish (&obs)); - obstack_free (&obs, NULL); - } - fputc ('\n', stderr); - return NULL; -} -#endif /* DEBUG_SYM */ diff --git a/m4/syntax.c b/m4/syntax.c deleted file mode 100644 index 4bde1234..00000000 --- a/m4/syntax.c +++ /dev/null @@ -1,954 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 2002, 2004, 2006-2010, 2013-2014, 2017 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 . -*/ - -#include - -#include "m4private.h" - -/* Define this to see runtime debug info. Implied by DEBUG. */ -/*#define DEBUG_SYNTAX */ - -/* THE SYNTAX TABLE - - The input is read character by character and grouped together - according to a syntax table. The character groups are (definitions - are all in m4module.h, those marked with a * are not yet in use): - - Basic (all characters fall in one of these mutually exclusive bins) - M4_SYNTAX_IGNORE *Character to be deleted from input as if not present - M4_SYNTAX_OTHER Any character with no special meaning to m4 - M4_SYNTAX_SPACE Whitespace (ignored when leading macro arguments) - M4_SYNTAX_OPEN Open list of macro arguments - M4_SYNTAX_CLOSE Close list of macro arguments - M4_SYNTAX_COMMA Separates macro arguments - M4_SYNTAX_ACTIVE This character is a macro name by itself - M4_SYNTAX_ESCAPE Use this character to prefix all macro names - - M4_SYNTAX_ALPHA Alphabetic characters (can start macro names) - M4_SYNTAX_NUM Numeric characters (can form macro names) - - M4_SYNTAX_LQUOTE A single character left quote - M4_SYNTAX_BCOMM A single character begin comment delimiter - - Attribute (these are context sensitive, and exist in addition to basic) - M4_SYNTAX_RQUOTE A single character right quote - M4_SYNTAX_ECOMM A single character end comment delimiter - M4_SYNTAX_DOLLAR Indicates macro argument in user macros - M4_SYNTAX_LBRACE *Indicates start of extended macro argument - M4_SYNTAX_RBRACE *Indicates end of extended macro argument - - Besides adding new facilities, the use of a syntax table will reduce - the number of calls to next_token (). Now groups of OTHER, NUM and - SPACE characters can be returned as a single token, since next_token - () knows they have no special syntactical meaning to m4. This is, - however, only possible if only single character quotes comments - comments are used, because otherwise the quote and comment characters - will not show up in the syntax-table. - - Having a syntax table allows new facilities. The new builtin - "changesyntax" allows the user to change the category of any - character. - - By default, '\n' is both ECOMM and SPACE, depending on the context. - Hence we have basic categories (mutually exclusive, can introduce a - context, and can be empty sets), and attribute categories - (additive, only recognized in context, and will never be empty). - - The precedence as implemented by next_token () is: - - M4_SYNTAX_IGNORE *Filtered out below next_token () - M4_SYNTAX_ESCAPE Reads macro name iff set, else next character - M4_SYNTAX_ALPHA Reads M4_SYNTAX_ALPHA and M4_SYNTAX_NUM as macro name - M4_SYNTAX_LQUOTE Reads all until balanced M4_SYNTAX_RQUOTE - M4_SYNTAX_BCOMM Reads all until M4_SYNTAX_ECOMM - - M4_SYNTAX_OTHER } Reads all M4_SYNTAX_OTHER, M4_SYNTAX_NUM - M4_SYNTAX_NUM } - - M4_SYNTAX_SPACE Reads all M4_SYNTAX_SPACE, depending on buffering - M4_SYNTAX_ACTIVE Returns a single char as a macro name - - M4_SYNTAX_OPEN } Returned as a single char - M4_SYNTAX_CLOSE } - M4_SYNTAX_COMMA } - - M4_SYNTAX_RQUOTE and M4_SYNTAX_ECOMM are context-sensitive, and - close out M4_SYNTAX_LQUOTE and M4_SYNTAX_BCOMM, respectively. - Also, M4_SYNTAX_DOLLAR, M4_SYNTAX_LBRACE, and M4_SYNTAX_RBRACE are - context-sensitive, only mattering when expanding macro definitions. - - There are several optimizations that can be performed depending on - known states of the syntax table. For example, when searching for - quotes, if there is only a single start quote and end quote - delimiter, we can use memchr2 and search a word at a time, instead - of performing a table lookup a byte at a time. The is_single_* - flags track whether quotes and comments have a single delimiter - (always the case if changequote/changecom were used, and - potentially the case after changesyntax). Since we frequently need - to access quotes, we store the oldest valid quote outside the - lookup table; the suspect flag tracks whether a cleanup pass is - needed to restore our invariants. On the other hand, coalescing - multiple M4_SYNTAX_OTHER bytes could form a delimiter, so many - optimizations must be disabled if a multi-byte delimiter exists; - this is handled by m4__safe_quotes. Meanwhile, quotes and comments - can be disabled if the leading delimiter is length 0. */ - -static int add_syntax_attribute (m4_syntax_table *, char, int); -static int remove_syntax_attribute (m4_syntax_table *, char, int); -static void set_quote_age (m4_syntax_table *, bool, bool); - -m4_syntax_table * -m4_syntax_create (void) -{ - m4_syntax_table *syntax = (m4_syntax_table *) xzalloc (sizeof *syntax); - int ch; - - /* Set up default table. This table never changes during operation, - and contains no context attributes. */ - for (ch = UCHAR_MAX + 1; --ch >= 0; ) - switch (ch) - { - case '(': - syntax->orig[ch] = M4_SYNTAX_OPEN; - break; - case ')': - syntax->orig[ch] = M4_SYNTAX_CLOSE; - break; - case ',': - syntax->orig[ch] = M4_SYNTAX_COMMA; - break; - case '`': - syntax->orig[ch] = M4_SYNTAX_LQUOTE; - break; - case '#': - syntax->orig[ch] = M4_SYNTAX_BCOMM; - break; - default: - if (isspace (ch)) - syntax->orig[ch] = M4_SYNTAX_SPACE; - else if (isalpha (ch) || ch == '_') - syntax->orig[ch] = M4_SYNTAX_ALPHA; - else if (isdigit (ch)) - syntax->orig[ch] = M4_SYNTAX_NUM; - else - syntax->orig[ch] = M4_SYNTAX_OTHER; - } - - /* Set up current table to match default. */ - m4_reset_syntax (syntax); - syntax->cached_simple.str1 = syntax->cached_lquote; - syntax->cached_simple.len1 = 1; - syntax->cached_simple.str2 = syntax->cached_rquote; - syntax->cached_simple.len2 = 1; - return syntax; -} - -void -m4_syntax_delete (m4_syntax_table *syntax) -{ - assert (syntax); - - free (syntax->quote.str1); - free (syntax->quote.str2); - free (syntax->comm.str1); - free (syntax->comm.str2); - free (syntax); -} - -int -m4_syntax_code (char ch) -{ - int code; - - switch (ch) - { - /* Sorted according to the order of M4_SYNTAX_* in m4module.h. */ - /* FIXME - revisit the ignore syntax attribute. */ - case 'I': case 'i': code = M4_SYNTAX_IGNORE; break; - /* Basic categories. */ - case '@': code = M4_SYNTAX_ESCAPE; break; - case 'W': case 'w': code = M4_SYNTAX_ALPHA; break; - case 'L': case 'l': code = M4_SYNTAX_LQUOTE; break; - case 'B': case 'b': code = M4_SYNTAX_BCOMM; break; - case 'A': case 'a': code = M4_SYNTAX_ACTIVE; break; - case 'D': case 'd': code = M4_SYNTAX_NUM; break; - case 'S': case 's': code = M4_SYNTAX_SPACE; break; - case '(': code = M4_SYNTAX_OPEN; break; - case ')': code = M4_SYNTAX_CLOSE; break; - case ',': code = M4_SYNTAX_COMMA; break; - case 'O': case 'o': code = M4_SYNTAX_OTHER; break; - /* Context categories. */ - case '$': code = M4_SYNTAX_DOLLAR; break; - case '{': code = M4_SYNTAX_LBRACE; break; - case '}': code = M4_SYNTAX_RBRACE; break; - case 'R': case 'r': code = M4_SYNTAX_RQUOTE; break; - case 'E': case 'e': code = M4_SYNTAX_ECOMM; break; - - default: code = -1; break; - } - - return code; -} - - - -/* Functions to manipulate the syntax table. */ -static int -add_syntax_attribute (m4_syntax_table *syntax, char ch, int code) -{ - int c = to_uchar (ch); - if (code & M4_SYNTAX_MASKS) - { - syntax->table[c] |= code; - syntax->suspect = true; - } - else - { - if ((code & (M4_SYNTAX_SUSPECT)) != 0 - || m4_has_syntax (syntax, c, M4_SYNTAX_SUSPECT)) - syntax->suspect = true; - syntax->table[c] = ((syntax->table[c] & M4_SYNTAX_MASKS) | code); - } - -#ifdef DEBUG_SYNTAX - xfprintf(stderr, "Set syntax %o %c = %04X\n", c, isprint(c) ? c : '-', - syntax->table[c]); -#endif - - return syntax->table[c]; -} - -static int -remove_syntax_attribute (m4_syntax_table *syntax, char ch, int code) -{ - int c = to_uchar (ch); - assert (code & M4_SYNTAX_MASKS); - syntax->table[c] &= ~code; - syntax->suspect = true; - -#ifdef DEBUG_SYNTAX - xfprintf(stderr, "Unset syntax %o %c = %04X\n", c, isprint(c) ? c : '-', - syntax->table[c]); -#endif - - return syntax->table[c]; -} - -/* Add the set CHARS of length LEN to syntax category CODE, removing - them from whatever category they used to be in. */ -static void -add_syntax_set (m4_syntax_table *syntax, const char *chars, size_t len, - int code) -{ - while (len--) - add_syntax_attribute (syntax, *chars++, code); -} - -/* Remove the set CHARS of length LEN from syntax category CODE, - adding them to category M4_SYNTAX_OTHER instead. */ -static void -subtract_syntax_set (m4_syntax_table *syntax, const char *chars, size_t len, - int code) -{ - while (len--) - { - char ch = *chars++; - if ((code & M4_SYNTAX_MASKS) != 0) - remove_syntax_attribute (syntax, ch, code); - else if (m4_has_syntax (syntax, ch, code)) - add_syntax_attribute (syntax, ch, M4_SYNTAX_OTHER); - } -} - -/* Make the set CHARS of length LEN become syntax category CODE, - removing CHARS from any other categories, and sending all bytes in - the category but not in CHARS to category M4_SYNTAX_OTHER - instead. */ -static void -set_syntax_set (m4_syntax_table *syntax, const char *chars, size_t len, - int code) -{ - int ch; - /* Explicit set of characters to install with this category; all - other characters that used to have the category get reset to - OTHER. */ - for (ch = UCHAR_MAX + 1; --ch >= 0; ) - { - if ((code & M4_SYNTAX_MASKS) != 0) - remove_syntax_attribute (syntax, ch, code); - else if (m4_has_syntax (syntax, ch, code)) - add_syntax_attribute (syntax, ch, M4_SYNTAX_OTHER); - } - while (len--) - { - ch = *chars++; - add_syntax_attribute (syntax, ch, code); - } -} - -/* Reset syntax category CODE to its default state, sending all other - characters in the category back to their default state. */ -static void -reset_syntax_set (m4_syntax_table *syntax, int code) -{ - int ch; - for (ch = UCHAR_MAX + 1; --ch >= 0; ) - { - /* Reset the category back to its default state. All other - characters that used to have this category get reset to - their default state as well. */ - if (code == M4_SYNTAX_RQUOTE) - { - if (ch == '\'') - add_syntax_attribute (syntax, ch, code); - else - remove_syntax_attribute (syntax, ch, code); - } - else if (code == M4_SYNTAX_ECOMM) - { - if (ch == '\n') - add_syntax_attribute (syntax, ch, code); - else - remove_syntax_attribute (syntax, ch, code); - } - else if (code == M4_SYNTAX_DOLLAR) - { - if (ch == '$') - add_syntax_attribute (syntax, ch, code); - else - remove_syntax_attribute (syntax, ch, code); - } - else if (code == M4_SYNTAX_LBRACE) - { - if (ch == '{') - add_syntax_attribute (syntax, ch, code); - else - remove_syntax_attribute (syntax, ch, code); - } - else if (code == M4_SYNTAX_RBRACE) - { - if (ch == '}') - add_syntax_attribute (syntax, ch, code); - else - remove_syntax_attribute (syntax, ch, code); - } - else if (syntax->orig[ch] == code || m4_has_syntax (syntax, ch, code)) - add_syntax_attribute (syntax, ch, syntax->orig[ch]); - } -} - -/* Reset the syntax table to its default state. */ -void -m4_reset_syntax (m4_syntax_table *syntax) -{ - /* Restore the default syntax, which has known quote and comment - properties. */ - memcpy (syntax->table, syntax->orig, sizeof syntax->orig); - - free (syntax->quote.str1); - free (syntax->quote.str2); - free (syntax->comm.str1); - free (syntax->comm.str2); - - /* The use of xmemdup0 is exploited by input.c. */ - syntax->quote.str1 = xmemdup0 (DEF_LQUOTE, 1); - syntax->quote.len1 = 1; - syntax->quote.str2 = xmemdup0 (DEF_RQUOTE, 1); - syntax->quote.len2 = 1; - syntax->comm.str1 = xmemdup0 (DEF_BCOMM, 1); - syntax->comm.len1 = 1; - syntax->comm.str2 = xmemdup0 (DEF_ECOMM, 1); - syntax->comm.len2 = 1; - syntax->dollar = '$'; - - add_syntax_attribute (syntax, syntax->quote.str2[0], M4_SYNTAX_RQUOTE); - add_syntax_attribute (syntax, syntax->comm.str2[0], M4_SYNTAX_ECOMM); - add_syntax_attribute (syntax, '$', M4_SYNTAX_DOLLAR); - add_syntax_attribute (syntax, '{', M4_SYNTAX_LBRACE); - add_syntax_attribute (syntax, '}', M4_SYNTAX_RBRACE); - - syntax->is_single_quotes = true; - syntax->is_single_comments = true; - syntax->is_single_dollar = true; - syntax->is_macro_escaped = false; - set_quote_age (syntax, true, false); -} - -/* Alter the syntax for category KEY, according to ACTION: '+' to add, - '-' to subtract, '=' to set, or '\0' to reset. The array CHARS of - length LEN describes the characters to modify; it is ignored if - ACTION is '\0'. Return -1 if KEY is invalid, otherwise return the - syntax category matching KEY. */ -int -m4_set_syntax (m4_syntax_table *syntax, char key, char action, - const char *chars, size_t len) -{ - int code; - - assert (syntax && chars); - code = m4_syntax_code (key); - if (code < 0) - { - return -1; - } - syntax->suspect = false; - switch (action) - { - case '+': - add_syntax_set (syntax, chars, len, code); - break; - case '-': - subtract_syntax_set (syntax, chars, len, code); - break; - case '=': - set_syntax_set (syntax, chars, len, code); - break; - case '\0': - assert (!len); - reset_syntax_set (syntax, code); - break; - default: - assert (false); - } - - /* Check for any cleanup needed. */ - if (syntax->suspect) - { - int ch; - int lquote = -1; - int rquote = -1; - int bcomm = -1; - int ecomm = -1; - bool single_quote_possible = true; - bool single_comm_possible = true; - int dollar = -1; - if (m4_has_syntax (syntax, syntax->quote.str1[0], M4_SYNTAX_LQUOTE)) - { - assert (syntax->quote.len1 == 1); - lquote = to_uchar (syntax->quote.str1[0]); - } - if (m4_has_syntax (syntax, syntax->quote.str2[0], M4_SYNTAX_RQUOTE)) - { - assert (syntax->quote.len2 == 1); - rquote = to_uchar (syntax->quote.str2[0]); - } - if (m4_has_syntax (syntax, syntax->comm.str1[0], M4_SYNTAX_BCOMM)) - { - assert (syntax->comm.len1 == 1); - bcomm = to_uchar (syntax->comm.str1[0]); - } - if (m4_has_syntax (syntax, syntax->comm.str2[0], M4_SYNTAX_ECOMM)) - { - assert (syntax->comm.len2 == 1); - ecomm = to_uchar (syntax->comm.str2[0]); - } - syntax->is_single_dollar = false; - syntax->is_macro_escaped = false; - /* Find candidates for each category. */ - for (ch = UCHAR_MAX + 1; --ch >= 0; ) - { - if (m4_has_syntax (syntax, ch, M4_SYNTAX_LQUOTE)) - { - if (lquote == -1) - lquote = ch; - else if (lquote != ch) - single_quote_possible = false; - } - if (m4_has_syntax (syntax, ch, M4_SYNTAX_RQUOTE)) - { - if (rquote == -1) - rquote = ch; - else if (rquote != ch) - single_quote_possible = false; - } - if (m4_has_syntax (syntax, ch, M4_SYNTAX_BCOMM)) - { - if (bcomm == -1) - bcomm = ch; - else if (bcomm != ch) - single_comm_possible = false; - } - if (m4_has_syntax (syntax, ch, M4_SYNTAX_ECOMM)) - { - if (ecomm == -1) - ecomm = ch; - else if (ecomm != ch) - single_comm_possible = false; - } - if (m4_has_syntax (syntax, ch, M4_SYNTAX_DOLLAR)) - { - if (dollar == -1) - { - syntax->dollar = dollar = ch; - syntax->is_single_dollar = true; - } - else - syntax->is_single_dollar = false; - } - if (m4_has_syntax (syntax, ch, M4_SYNTAX_ESCAPE)) - syntax->is_macro_escaped = true; - } - /* Disable multi-character delimiters if we discovered - delimiters. */ - if (!single_quote_possible) - syntax->is_single_quotes = false; - if (!single_comm_possible) - syntax->is_single_comments = false; - if ((1 < syntax->quote.len1 || 1 < syntax->quote.len2) - && (!syntax->is_single_quotes || lquote != -1 || rquote != -1)) - { - if (syntax->quote.len1) - { - syntax->quote.len1 = lquote == to_uchar (syntax->quote.str1[0]); - syntax->quote.str1[syntax->quote.len1] = '\0'; - } - if (syntax->quote.len2) - { - syntax->quote.len2 = rquote == to_uchar (syntax->quote.str2[0]); - syntax->quote.str2[syntax->quote.len2] = '\0'; - } - } - if ((1 < syntax->comm.len1 || 1 < syntax->comm.len2) - && (!syntax->is_single_comments || bcomm != -1 || ecomm != -1)) - { - if (syntax->comm.len1) - { - syntax->comm.len1 = bcomm == to_uchar (syntax->comm.str1[0]); - syntax->comm.str1[syntax->comm.len1] = '\0'; - } - if (syntax->comm.len2) - { - syntax->comm.len2 = ecomm == to_uchar (syntax->comm.str2[0]); - syntax->comm.str2[syntax->comm.len2] = '\0'; - } - } - /* Update the strings. */ - if (lquote != -1) - { - if (single_quote_possible) - syntax->is_single_quotes = true; - if (syntax->quote.len1) - assert (syntax->quote.len1 == 1); - else - { - free (syntax->quote.str1); - syntax->quote.str1 = xcharalloc (2); - syntax->quote.str1[1] = '\0'; - syntax->quote.len1 = 1; - } - syntax->quote.str1[0] = lquote; - if (rquote == -1) - { - rquote = '\''; - add_syntax_attribute (syntax, rquote, M4_SYNTAX_RQUOTE); - } - if (!syntax->quote.len2) - { - free (syntax->quote.str2); - syntax->quote.str2 = xcharalloc (2); - } - syntax->quote.str2[0] = rquote; - syntax->quote.str2[1] = '\0'; - syntax->quote.len2 = 1; - } - if (bcomm != -1) - { - if (single_comm_possible) - syntax->is_single_comments = true; - if (syntax->comm.len1) - assert (syntax->comm.len1 == 1); - else - { - free (syntax->comm.str1); - syntax->comm.str1 = xcharalloc (2); - syntax->comm.str1[1] = '\0'; - syntax->comm.len1 = 1; - } - syntax->comm.str1[0] = bcomm; - if (ecomm == -1) - { - ecomm = '\n'; - add_syntax_attribute (syntax, ecomm, M4_SYNTAX_ECOMM); - } - if (!syntax->comm.len2) - { - free (syntax->comm.str2); - syntax->comm.str2 = xcharalloc (2); - } - syntax->comm.str2[0] = ecomm; - syntax->comm.str2[1] = '\0'; - syntax->comm.len2 = 1; - } - } - set_quote_age (syntax, false, true); - m4__quote_uncache (syntax); - return code; -} - - -/* Functions for setting quotes and comment delimiters. Used by - m4_changecom () and m4_changequote (). Both functions override the - syntax table to maintain compatibility. */ - -/* Set the quote delimiters to LQ and RQ, with respective lengths - LQ_LEN and RQ_LEN. Pass NULL if the argument was not present, to - distinguish from an explicit empty string. */ -void -m4_set_quotes (m4_syntax_table *syntax, const char *lq, size_t lq_len, - const char *rq, size_t rq_len) -{ - int ch; - - assert (syntax); - - /* POSIX states that with 0 arguments, the default quotes are used. - POSIX XCU ERN 112 states that behavior is implementation-defined - if there was only one argument, or if there is an empty string in - either position when there are two arguments. We allow an empty - left quote to disable quoting, but a non-empty left quote will - always create a non-empty right quote. See the texinfo for what - some other implementations do. */ - if (!lq) - { - lq = DEF_LQUOTE; - lq_len = 1; - rq = DEF_RQUOTE; - rq_len = 1; - } - else if (!rq || (lq_len && !rq_len)) - { - rq = DEF_RQUOTE; - rq_len = 1; - } - - if (syntax->quote.len1 == lq_len && syntax->quote.len2 == rq_len - && memcmp (syntax->quote.str1, lq, lq_len) == 0 - && memcmp (syntax->quote.str2, rq, rq_len) == 0) - return; - - free (syntax->quote.str1); - free (syntax->quote.str2); - /* The use of xmemdup0 is exploited by input.c. */ - syntax->quote.str1 = xmemdup0 (lq, lq_len); - syntax->quote.len1 = lq_len; - syntax->quote.str2 = xmemdup0 (rq, rq_len); - syntax->quote.len2 = rq_len; - - /* changequote overrides syntax_table, but be careful when it is - used to select a start-quote sequence that is effectively - disabled. */ - syntax->is_single_quotes = true; - for (ch = UCHAR_MAX + 1; --ch >= 0; ) - { - if (m4_has_syntax (syntax, ch, M4_SYNTAX_LQUOTE)) - add_syntax_attribute (syntax, ch, - (syntax->orig[ch] == M4_SYNTAX_LQUOTE - ? M4_SYNTAX_OTHER : syntax->orig[ch])); - if (m4_has_syntax (syntax, ch, M4_SYNTAX_RQUOTE)) - remove_syntax_attribute (syntax, ch, M4_SYNTAX_RQUOTE); - } - - if (!m4_has_syntax (syntax, *syntax->quote.str1, - (M4_SYNTAX_IGNORE | M4_SYNTAX_ESCAPE | M4_SYNTAX_ALPHA - | M4_SYNTAX_NUM))) - { - if (syntax->quote.len1 == 1) - add_syntax_attribute (syntax, syntax->quote.str1[0], M4_SYNTAX_LQUOTE); - if (syntax->quote.len2 == 1) - add_syntax_attribute (syntax, syntax->quote.str2[0], M4_SYNTAX_RQUOTE); - } - set_quote_age (syntax, false, false); -} - -/* Set the comment delimiters to BC and EC, with respective lengths - BC_LEN and EC_LEN. Pass NULL if the argument was not present, to - distinguish from an explicit empty string. */ -void -m4_set_comment (m4_syntax_table *syntax, const char *bc, size_t bc_len, - const char *ec, size_t ec_len) -{ - int ch; - - assert (syntax); - - /* POSIX requires no arguments to disable comments, and that one - argument use newline as the close-comment. POSIX XCU ERN 131 - states that empty arguments invoke implementation-defined - behavior. We allow an empty begin comment to disable comments, - and a non-empty begin comment will always create a non-empty end - comment. See the texinfo for what some other implementations - do. */ - if (!bc) - { - bc = ec = ""; - bc_len = ec_len = 0; - } - else if (!ec || (bc_len && !ec_len)) - { - ec = DEF_ECOMM; - ec_len = 1; - } - - if (syntax->comm.len1 == bc_len && syntax->comm.len2 == ec_len - && memcmp (syntax->comm.str1, bc, bc_len) == 0 - && memcmp (syntax->comm.str2, ec, ec_len) == 0) - return; - - free (syntax->comm.str1); - free (syntax->comm.str2); - /* The use of xmemdup0 is exploited by input.c. */ - syntax->comm.str1 = xmemdup0 (bc, bc_len); - syntax->comm.len1 = bc_len; - syntax->comm.str2 = xmemdup0 (ec, ec_len); - syntax->comm.len2 = ec_len; - - /* changecom overrides syntax_table, but be careful when it is used - to select a start-comment sequence that is effectively - disabled. */ - syntax->is_single_comments = true; - for (ch = UCHAR_MAX + 1; --ch >= 0; ) - { - if (m4_has_syntax (syntax, ch, M4_SYNTAX_BCOMM)) - add_syntax_attribute (syntax, ch, - (syntax->orig[ch] == M4_SYNTAX_BCOMM - ? M4_SYNTAX_OTHER : syntax->orig[ch])); - if (m4_has_syntax (syntax, ch, M4_SYNTAX_ECOMM)) - remove_syntax_attribute (syntax, ch, M4_SYNTAX_ECOMM); - } - if (!m4_has_syntax (syntax, *syntax->comm.str1, - (M4_SYNTAX_IGNORE | M4_SYNTAX_ESCAPE | M4_SYNTAX_ALPHA - | M4_SYNTAX_NUM | M4_SYNTAX_LQUOTE))) - { - if (syntax->comm.len1 == 1) - add_syntax_attribute (syntax, syntax->comm.str1[0], M4_SYNTAX_BCOMM); - if (syntax->comm.len2 == 1) - add_syntax_attribute (syntax, syntax->comm.str2[0], M4_SYNTAX_ECOMM); - } - set_quote_age (syntax, false, false); -} - -/* Call this when changing anything that might impact the quote age, - so that m4__quote_age and m4__safe_quotes will reflect the change. - If RESET, changesyntax was reset to its default stage; if CHANGE, - arbitrary syntax has changed; otherwise, just quotes or comment - delimiters have changed. */ -static void -set_quote_age (m4_syntax_table *syntax, bool reset, bool change) -{ - /* Multi-character quotes are inherently unsafe, since concatenation - of individual characters can result in a quote delimiter, - consider: - - define(echo,``$1'')define(a,A)changequote(<[,]>)echo(<[]]><[>a]>) - => A]> (not ]>a) - - Also, unquoted close delimiters are unsafe, consider: - - define(echo,``$1'')define(a,A)echo(`a''`a') - => aA' (not a'a) - - Duplicated start and end quote delimiters, as well as comment - delimiters that overlap with quote delimiters or active characters, - also present a problem, consider: - - define(echo,$*)echo(a,a,a`'define(a,A)changecom(`,',`,')) - => A,a,A (not A,A,A) - - The impact of arbitrary changesyntax is difficult to characterize. - So if things are in their default state, we use 0 for the upper 16 - bits of quote_age; otherwise we increment syntax_age for each - changesyntax, but saturate it at 0xffff rather than wrapping - around. Perhaps a cache of other frequently used states is - warranted, if changesyntax becomes more popular. - - Perhaps someday we will fix $@ expansion to use the current - settings of the comma category, or even allow multi-character - argument separators via changesyntax. Until then, we use a literal - `,' in $@ expansion, therefore we must insist that `,' be an - argument separator for quote_age to be non-zero. - - Rather than check every token for an unquoted delimiter, we merely - encode current_quote_age to 0 when things are unsafe, and non-zero - when safe (namely, the syntax_age in the upper 16 bits, coupled - with the 16-bit value composed of the single-character start and - end quote delimiters). There may be other situations which are - safe even when this algorithm sets the quote_age to zero, but at - least a quote_age of zero always produces correct results (although - it may take more time in doing so). */ - - unsigned short local_syntax_age; - if (reset) - local_syntax_age = 0; - else if (change && syntax->syntax_age < 0xffff) - local_syntax_age = ++syntax->syntax_age; - else - local_syntax_age = syntax->syntax_age; - if (local_syntax_age < 0xffff && syntax->is_single_quotes - && syntax->quote.len1 == 1 && syntax->quote.len2 == 1 - && !m4_has_syntax (syntax, *syntax->quote.str1, - (M4_SYNTAX_ALPHA | M4_SYNTAX_NUM | M4_SYNTAX_OPEN - | M4_SYNTAX_COMMA | M4_SYNTAX_CLOSE - | M4_SYNTAX_SPACE)) - && !m4_has_syntax (syntax, *syntax->quote.str2, - (M4_SYNTAX_ALPHA | M4_SYNTAX_NUM | M4_SYNTAX_OPEN - | M4_SYNTAX_COMMA | M4_SYNTAX_CLOSE - | M4_SYNTAX_SPACE)) - && *syntax->quote.str1 != *syntax->quote.str2 - && (!syntax->comm.len1 - || (*syntax->comm.str1 != *syntax->quote.str2 - && !m4_has_syntax (syntax, *syntax->comm.str1, - (M4_SYNTAX_OPEN | M4_SYNTAX_COMMA - | M4_SYNTAX_CLOSE)))) - && m4_has_syntax (syntax, ',', M4_SYNTAX_COMMA)) - { - syntax->quote_age = ((local_syntax_age << 16) - | ((*syntax->quote.str1 & 0xff) << 8) - | (*syntax->quote.str2 & 0xff)); - } - else - syntax->quote_age = 0; -} - -/* Interface for caching frequently used quote pairs, independently of - the current quote delimiters (for example, consider a text macro - expansion that includes several copies of $@), and using AGE for - optimization. If QUOTES is NULL, don't use quoting. If OBS is - non-NULL, AGE should be the current quote age, and QUOTES should be - m4_get_syntax_quotes; the return value will be a cached quote pair, - where the pointer is valid at least as long as OBS is not reset, - but whose contents are only guaranteed until the next changequote - or quote_cache. Otherwise, OBS is NULL, AGE should be the same as - before, and QUOTES should be a previously returned cache value; - used to refresh the contents of the result. */ -const m4_string_pair * -m4__quote_cache (m4_syntax_table *syntax, m4_obstack *obs, unsigned int age, - const m4_string_pair *quotes) -{ - /* Implementation - if AGE is non-zero, then the implementation of - set_quote_age guarantees that we can recreate the return value on - the fly; so we use static storage, and the contents must be used - immediately. If AGE is zero, then we must copy QUOTES onto OBS, - but we might as well cache that copy. */ - if (!quotes) - return NULL; - if (age) - { - *syntax->cached_lquote = (age >> 8) & 0xff; - *syntax->cached_rquote = age & 0xff; - return &syntax->cached_simple; - } - if (!obs) - return quotes; - assert (quotes == &syntax->quote); - if (!syntax->cached_quote) - { - assert (obstack_object_size (obs) == 0); - syntax->cached_quote = (m4_string_pair *) obstack_copy (obs, quotes, - sizeof *quotes); - syntax->cached_quote->str1 = (char *) obstack_copy0 (obs, quotes->str1, - quotes->len1); - syntax->cached_quote->str2 = (char *) obstack_copy0 (obs, quotes->str2, - quotes->len2); - } - return syntax->cached_quote; -} - - -/* Define these functions at the end, so that calls in the file use the - faster macro version from m4module.h. */ -#undef m4_get_syntax_lquote -const char * -m4_get_syntax_lquote (m4_syntax_table *syntax) -{ - assert (syntax); - return syntax->quote.str1; -} - -#undef m4_get_syntax_rquote -const char * -m4_get_syntax_rquote (m4_syntax_table *syntax) -{ - assert (syntax); - return syntax->quote.str2; -} - -#undef m4_get_syntax_quotes -const m4_string_pair * -m4_get_syntax_quotes (m4_syntax_table *syntax) -{ - assert (syntax); - return &syntax->quote; -} - -#undef m4_is_syntax_single_quotes -bool -m4_is_syntax_single_quotes (m4_syntax_table *syntax) -{ - assert (syntax); - return syntax->is_single_quotes; -} - -#undef m4_get_syntax_bcomm -const char * -m4_get_syntax_bcomm (m4_syntax_table *syntax) -{ - assert (syntax); - return syntax->comm.str1; -} - -#undef m4_get_syntax_ecomm -const char * -m4_get_syntax_ecomm (m4_syntax_table *syntax) -{ - assert (syntax); - return syntax->comm.str2; -} - -#undef m4_get_syntax_comments -const m4_string_pair * -m4_get_syntax_comments (m4_syntax_table *syntax) -{ - assert (syntax); - return &syntax->comm; -} - -#undef m4_is_syntax_single_comments -bool -m4_is_syntax_single_comments (m4_syntax_table *syntax) -{ - assert (syntax); - return syntax->is_single_comments; -} - -#undef m4_is_syntax_single_dollar -bool -m4_is_syntax_single_dollar (m4_syntax_table *syntax) -{ - assert (syntax); - return syntax->is_single_dollar; -} - -#undef m4_is_syntax_macro_escaped -bool -m4_is_syntax_macro_escaped (m4_syntax_table *syntax) -{ - assert (syntax); - return syntax->is_macro_escaped; -} diff --git a/m4/system_.h b/m4/system_.h deleted file mode 100644 index 7176b383..00000000 --- a/m4/system_.h +++ /dev/null @@ -1,173 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 2000-2001, 2003, 2006-2008, 2010, 2013-2014, 2017 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 . -*/ - -/** - * @configure_output@ - * - * This file is installed, so cannot rely on the contents of config.h. - * It works best if included _before_ system headers. - **/ - -#ifndef M4_SYSTEM_H -#define M4_SYSTEM_H 1 - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - - -@INCLUDE_ERROR_H@ -@INCLUDE_OBSTACK_H@ -@INCLUDE_REGEX_H@ -@INCLUDE_STDBOOL_H@ - -#include -#include -#include - -/* In addition to EXIT_SUCCESS and EXIT_FAILURE, m4 can fail with version - mismatch when trying to load a frozen file produced by a newer m4 than - the version doing the reload. */ -#define EXIT_MISMATCH 63 - -/* This is okay in an installed file, because it will not change the - behaviour of the including program whether ENABLE_NLS is defined - or not. */ -#ifndef _ -# ifdef ENABLE_NLS -# include -# define _(Text) gettext (Text) -# define N_(Text) gettext_noop (Text) -# else -# define _(Text) (Text) -# define N_(Text) (Text) -# endif -#endif - - -/* All header files should be inside BEGIN_C_DECLS ... END_C_DECLS, so - that the library can be linked into a C++ program. The multi-include - guard macros must be outside, as should any #includes -- for simplicity - everything else should go inside. */ - -#ifndef BEGIN_C_DECLS -# ifdef __cplusplus -# define BEGIN_C_DECLS extern "C" { -# define END_C_DECLS } -# else /* !__cplusplus */ -# define BEGIN_C_DECLS /* empty */ -# define END_C_DECLS /* empty */ -# endif /* __cplusplus */ -#endif /* !BEGIN_C_DECLS */ - -BEGIN_C_DECLS - - - -/* Canonicalize UNIX recognition macros. */ -#if defined unix || defined __unix || defined __unix__ \ - || defined _POSIX_VERSION || defined _POSIX2_VERSION \ - || defined __NetBSD__ || defined __OpenBSD__ \ - || defined __APPLE__ || defined __APPLE_CC__ -# define UNIX 1 -#endif - -/* Canonicalize Windows recognition macros. */ -#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__ -# define W32_NATIVE 1 -#endif - -/* Canonicalize OS/2 recognition macro. */ -#ifdef __EMX__ -# define OS2 1 -# undef UNIX -#endif - - -/* M4_STMT_START/END are used to create macros which expand to a - a single compound statement in a portable way, but crucially in - a way sympathetic to the compiler to maximise optimization. */ -#undef M4_STMT_START -#undef M4_STMT_END -#if defined __GNUC__ && !defined __STRICT_ANSI__ && !defined __cplusplus -# define M4_STMT_START (void)( -# define M4_STMT_END ) -#else -# if defined sun || defined __sun__ -# define M4_STMT_START if (1) -# define M4_STMT_END else (void)0 -# else -# define M4_STMT_START do -# define M4_STMT_END while (0) -# endif -#endif - - - -/* Take advantage of GNU C compiler source level optimization hints, - using portable macros. */ -#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 6) -# define M4_GNUC_ATTRIBUTE(args) __attribute__ (args) -#else -# define M4_GNUC_ATTRIBUTE(args) -#endif /* __GNUC__ */ - -#define M4_GNUC_PRINTF(fmt, arg) \ - M4_GNUC_ATTRIBUTE ((__format__ (__printf__, fmt, arg))) -#define M4_GNUC_SCANF(fmt, arg) \ - M4_GNUC_ATTRIBUTE ((__format__ (__scanf__, fmt, arg))) -#define M4_GNUC_NORETURN M4_GNUC_ATTRIBUTE ((__noreturn__)) -#define M4_GNUC_CONST M4_GNUC_ATTRIBUTE ((__const__)) -#define M4_GNUC_UNUSED M4_GNUC_ATTRIBUTE ((__unused__)) -#define M4_GNUC_PURE M4_GNUC_ATTRIBUTE ((__pure__)) - - - -#if !defined __PRETTY_FUNCTION__ -# define __PRETTY_FUNCTION__ "" -#endif - - -/* Preprocessor token manipulation. */ - -/* The extra indirection to the _STR and _CONC macros is required so that - if the arguments to STR() (or CONC()) are themselves macros, they will - be expanded before being quoted. */ -#ifndef STR -# define _STR(arg) #arg -# define STR(arg) _STR (arg) -#endif - -#ifndef CONC -# define _CONC(a, b) a##b -# define CONC(a, b) _CONC (a, b) -#endif - -END_C_DECLS - -#endif /* !M4_SYSTEM_H */ diff --git a/m4/utility.c b/m4/utility.c deleted file mode 100644 index 2063c6a3..00000000 --- a/m4/utility.c +++ /dev/null @@ -1,292 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 1998-1999, 2003, 2006-2010, 2013-2014, 2017 - 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 . -*/ - -#include - -#include "m4private.h" - -#include "exitfail.h" -#include "progname.h" -#include "quotearg.h" -#include "verror.h" -#include "xvasprintf.h" - -static const char *skip_space (m4 *, const char *); - - - -/* Give friendly warnings if a builtin macro is passed an - inappropriate number of arguments. MIN is the 0-based minimum - number of acceptable arguments, MAX is the 0-based maximum number - or UINT_MAX if not applicable, and SIDE_EFFECT is true if the macro - has side effects even if min is not satisfied. ARGC is the 1-based - count of supplied arguments, and CALLER is the name of the macro. - Return true if the macro is guaranteed to expand to the empty - string, false otherwise. */ -bool -m4_bad_argc (m4 *context, size_t argc, const m4_call_info *caller, size_t min, - size_t max, bool side_effect) -{ - if (argc - 1 < min) - { - m4_warn (context, 0, caller, _("too few arguments: %zu < %zu"), - argc - 1, min); - return !side_effect; - } - - if (argc - 1 > max) - { - m4_warn (context, 0, caller, _("extra arguments ignored: %zu > %zu"), - argc - 1, max); - } - - return false; -} - -static const char * -skip_space (m4 *context, const char *arg) -{ - while (m4_has_syntax (M4SYNTAX, *arg, M4_SYNTAX_SPACE)) - arg++; - return arg; -} - -/* The function m4_numeric_arg () converts ARG of length LEN to an int - pointed to by VALUEP. If the conversion fails, print error message - for CALLER. Return true iff conversion succeeds. */ -/* FIXME: Convert this to use gnulib's xstrtoimax, xstrtoumax. - Otherwise, we are arbitrarily limiting integer values. */ -bool -m4_numeric_arg (m4 *context, const m4_call_info *caller, const char *arg, - size_t len, int *valuep) -{ - char *endp; - - if (!len) - { - *valuep = 0; - m4_warn (context, 0, caller, _("empty string treated as 0")); - } - else - { - const char *str = skip_space (context, arg); - *valuep = strtol (str, &endp, 10); - if (endp - arg != len) - { - m4_warn (context, 0, caller, _("non-numeric argument %s"), - quotearg_style_mem (locale_quoting_style, arg, len)); - return false; - } - if (str != arg) - m4_warn (context, 0, caller, _("leading whitespace ignored")); - else if (errno == ERANGE) - m4_warn (context, 0, caller, _("numeric overflow detected")); - } - return true; -} - -/* Parse ARG of length LEN as a truth value. If ARG is NUL, use "" - instead; otherwise, ARG must have a NUL-terminator (even if it also - has embedded NUL). If LEN is SIZE_MAX, use the string length of - ARG. If unrecognized, issue a warning on behalf of CALLER and - return PREVIOUS; otherwise return the parsed value. */ -bool -m4_parse_truth_arg (m4 *context, const m4_call_info *caller, const char *arg, - size_t len, bool previous) -{ - /* 0, no, off, blank... */ - if (!arg || len == 0 - || arg[0] == '0' - || arg[0] == 'n' || arg[0] == 'N' - || ((arg[0] == 'o' || arg[0] == 'O') - && (arg[1] == 'f' || arg[1] == 'F'))) - return false; - /* 1, yes, on... */ - if (arg[0] == '1' - || arg[0] == 'y' || arg[0] == 'Y' - || ((arg[0] == 'o' || arg[0] == 'O') - && (arg[1] == 'n' || arg[1] == 'N'))) - return true; - m4_warn (context, 0, caller, _("unknown directive %s"), - quotearg_style_mem (locale_quoting_style, arg, len)); - return previous; -} - -/* Helper method to look up a symbol table entry given an argument. - Warn on behalf of ARGV if VALUE is not a text argument, or if - MUST_EXIST and no macro exists by the name in VALUE. Return the - result of the lookup, or NULL. */ -m4_symbol * -m4_symbol_value_lookup (m4 *context, m4_macro_args *argv, size_t i, - bool must_exist) -{ - m4_symbol *result = NULL; - if (m4_is_arg_text (argv, i)) - { - const char *name = M4ARG (i); - size_t len = M4ARGLEN (i); - result = m4_symbol_lookup (M4SYMTAB, name, len); - if (must_exist && !result - && m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF)) - m4_warn (context, 0, argv->info, _("undefined macro %s"), - quotearg_style_mem (locale_quoting_style, name, len)); - } - else - m4_warn (context, 0, argv->info, _("invalid macro name ignored")); - return result; -} - -/* Return an escaped version of the macro name corresponding to - CALLER, for use in error messages that do not use the m4_warn - machinery. This call occupies slot 0 of the quotearg - machinery. */ -const char *m4_info_name (const m4_call_info *caller) -{ - return quotearg_style_mem (locale_quoting_style, caller->name, - caller->name_len); -} - -/* Helper for all error reporting. Report message based on FORMAT and - ARGS, on behalf of CALLER (if any), otherwise at the global - position in CONTEXT. If ERRNUM, decode the errno value as part of - the message. If STATUS, exit immediately with that status. If - WARN, prepend 'warning: '. */ -static void -m4_verror_at_line (m4 *context, bool warn, int status, int errnum, - const m4_call_info *caller, const char *format, - va_list args) -{ - char *full = NULL; - char *safe_macro = NULL; - const char *macro = caller ? caller->name : NULL; - size_t len = caller ? caller->name_len : 0; - const char *file = caller ? caller->file : m4_get_current_file (context); - int line = caller ? caller->line : m4_get_current_line (context); - - assert (file || !line); - /* Sanitize MACRO, since we are turning around and using it in a - format string. The allocation is overly conservative, but - problematic macro names only occur via indir or changesyntax. */ - if (macro && memchr (macro, '%', len)) - { - char *p = safe_macro = xcharalloc (2 * len); - const char *end = macro + len; - while (macro != end) - { - if (*macro == '%') - { - *p++ = '%'; - len++; - } - *p++ = *macro++; - } - } - if (macro) - /* Use slot 1, so that the rest of the code can use the simpler - quotearg interface in slot 0. */ - macro = quotearg_n_mem (1, safe_macro ? safe_macro : macro, len); - /* Prepend warning and the macro name, as needed. But if that fails - for non-memory reasons (unlikely), then still use the original - format. */ - if (warn && macro) - full = xasprintf (_("warning: %s: %s"), macro, format); - else if (warn) - full = xasprintf (_("warning: %s"), format); - else if (macro) - full = xasprintf (_("%s: %s"), macro, format); - verror_at_line (status, errnum, line ? file : NULL, line, - full ? full : format, args); - free (full); - free (safe_macro); - if ((!warn || m4_get_fatal_warnings_opt (context)) - && !m4_get_exit_status (context)) - m4_set_exit_status (context, EXIT_FAILURE); -} - -/* Issue an error. The message is printf-style, based on FORMAT and - any other arguments, and the program name and location (if we are - currently parsing an input file) are automatically prepended. If - ERRNUM is non-zero, include strerror output in the message. If - CALLER, prepend the message with the macro where the message - occurred. If STATUS is non-zero, or if errors are fatal, call exit - immediately; otherwise, remember that an error occurred so that m4 - cannot exit with success later on.*/ -void -m4_error (m4 *context, int status, int errnum, const m4_call_info *caller, - const char *format, ...) -{ - va_list args; - va_start (args, format); - if (status == EXIT_SUCCESS && m4_get_warnings_exit_opt (context)) - status = EXIT_FAILURE; - m4_verror_at_line (context, false, status, errnum, caller, format, args); - va_end (args); -} - -/* Issue a warning, if they are not being suppressed. The message is - printf-style, based on FORMAT and any other arguments, and the - program name, location (if we are currently parsing an input file), - and "warning:" are automatically prepended. If ERRNUM is non-zero, - include strerror output in the message. If CALLER, prepend the - message with the macro where the message occurred. If warnings are - fatal, call exit immediately, otherwise exit status is - unchanged. */ -void -m4_warn (m4 *context, int errnum, const m4_call_info *caller, - const char *format, ...) -{ - if (!m4_get_suppress_warnings_opt (context)) - { - va_list args; - int status = EXIT_SUCCESS; - va_start (args, format); - if (m4_get_warnings_exit_opt (context)) - status = EXIT_FAILURE; - m4_verror_at_line (context, true, status, errnum, caller, format, args); - va_end (args); - } -} - -/* Wrap the gnulib progname module, to avoid exporting a global - variable from a library. Retrieve the program name for use in - error messages and the __program__ macro. */ -const char * -m4_get_program_name (void) -{ - return program_name; -} - -/* Wrap the gnulib progname module, to avoid exporting a global - variable from a library. Set the program name for use in error - messages and the __program__ macro to argv[0]. */ -void -m4_set_program_name (const char *name) -{ - set_program_name (name); -} - -/* Wrap the gnulib exitfail module, to avoid exporting a global - variable from a library. Set the exit status for use in gnulib - modules and atexit handlers. */ -void -m4_set_exit_failure (int status) -{ - exit_failure = status; -} diff --git a/modules/evalparse.c b/modules/evalparse.c deleted file mode 100644 index d70d6060..00000000 --- a/modules/evalparse.c +++ /dev/null @@ -1,1029 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 2001, 2006-2010, 2013-2014, 2017 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 . -*/ - -/* This file contains the functions to evaluate integer expressions - for the "eval" and "evalmp" builtins. It is a little, fairly - self-contained module, with its own scanner, and a recursive descent - parser. - - It has been carefully factored for use from the GMP module builtin, - mpeval: any actual operation performed on numbers is abstracted by - a set of macro definitions. For plain `eval', `number' is some - long int type, and `numb_*' manipulate those long ints. When - using GMP, `number' is typedef'd to `mpq_t' (the arbritrary - precision fractional numbers type of GMP), and `numb_*' are mapped - to GMP functions. - - There is only one entry point, `m4_evaluate', a single function for - both `eval' and `mpeval', but which is redefined appropriately when - this file is #included into its clients. */ - -#include "quotearg.h" - -typedef enum eval_token - { - ERROR, BADOP, - PLUS, MINUS, - EXPONENT, - TIMES, DIVIDE, MODULO, RATIO, - EQ, NOTEQ, GT, GTEQ, LS, LSEQ, - LSHIFT, RSHIFT, URSHIFT, - LNOT, LAND, LOR, - NOT, AND, OR, XOR, - LEFTP, RIGHTP, - QUESTION, COLON, COMMA, - NUMBER, EOTEXT - } -eval_token; - -/* Error types. */ - -typedef enum eval_error - { - NO_ERROR, - DIVIDE_ZERO, - MODULO_ZERO, - NEGATIVE_EXPONENT, - /* All errors prior to SYNTAX_ERROR can be ignored in a dead - branch of && and ||. All errors after are just more details - about a syntax error. */ - SYNTAX_ERROR, - MISSING_RIGHT, - MISSING_COLON, - UNKNOWN_INPUT, - EXCESS_INPUT, - INVALID_OPERATOR - } -eval_error; - -static eval_error comma_term (m4 *, eval_token, number *); -static eval_error condition_term (m4 *, eval_token, number *); -static eval_error logical_or_term (m4 *, eval_token, number *); -static eval_error logical_and_term (m4 *, eval_token, number *); -static eval_error or_term (m4 *, eval_token, number *); -static eval_error xor_term (m4 *, eval_token, number *); -static eval_error and_term (m4 *, eval_token, number *); -static eval_error equality_term (m4 *, eval_token, number *); -static eval_error cmp_term (m4 *, eval_token, number *); -static eval_error shift_term (m4 *, eval_token, number *); -static eval_error add_term (m4 *, eval_token, number *); -static eval_error mult_term (m4 *, eval_token, number *); -static eval_error exp_term (m4 *, eval_token, number *); -static eval_error unary_term (m4 *, eval_token, number *); -static eval_error simple_term (m4 *, eval_token, number *); -static eval_error numb_pow (number *, number *); - - - -/* --- LEXICAL FUNCTIONS --- */ - -/* Pointer to next character of input text. */ -static const char *eval_text; - -/* Value of eval_text, from before last call of eval_lex (). This is so we - can back up, if we have read too much. */ -static const char *last_text; - -/* Detect when to end parsing. */ -static const char *end_text; - -/* Prime the lexer at the start of TEXT, with length LEN. */ -static void -eval_init_lex (const char *text, size_t len) -{ - eval_text = text; - end_text = text + len; - last_text = NULL; -} - -static void -eval_undo (void) -{ - eval_text = last_text; -} - -/* VAL is numerical value, if any. Recognize C assignment operators, - even though we cannot support them, to issue better error - messages. */ - -static eval_token -eval_lex (number *val) -{ - while (eval_text != end_text && isspace (to_uchar (*eval_text))) - eval_text++; - - last_text = eval_text; - - if (eval_text == end_text) - return EOTEXT; - - if (isdigit (to_uchar (*eval_text))) - { - int base, digit; - - if (*eval_text == '0') - { - eval_text++; - switch (*eval_text) - { - case 'x': - case 'X': - base = 16; - eval_text++; - break; - - case 'b': - case 'B': - base = 2; - eval_text++; - break; - - case 'r': - case 'R': - base = 0; - eval_text++; - while (isdigit (to_uchar (*eval_text)) && base <= 36) - base = 10 * base + *eval_text++ - '0'; - if (base == 0 || base > 36 || *eval_text != ':') - return ERROR; - eval_text++; - break; - - default: - base = 8; - } - } - else - base = 10; - - numb_set_si (val, 0); - for (; *eval_text; eval_text++) - { - if (isdigit (to_uchar (*eval_text))) - digit = *eval_text - '0'; - else if (islower (to_uchar (*eval_text))) - digit = *eval_text - 'a' + 10; - else if (isupper (to_uchar (*eval_text))) - digit = *eval_text - 'A' + 10; - else - break; - - if (base == 1) - { - if (digit == 1) - numb_incr (*val); - else if (digit == 0 && numb_zerop (*val)) - continue; - else - break; - } - else if (digit >= base) - break; - else - { - number xbase; - number xdigit; - - /* (*val) = (*val) * base; */ - numb_init (xbase); - numb_set_si (&xbase, base); - numb_times (*val, xbase); - numb_fini (xbase); - /* (*val) = (*val) + digit; */ - numb_init (xdigit); - numb_set_si (&xdigit, digit); - numb_plus (*val, xdigit); - numb_fini (xdigit); - } - } - return NUMBER; - } - - switch (*eval_text++) - { - case '+': - if (*eval_text == '+' || *eval_text == '=') - return BADOP; - return PLUS; - case '-': - if (*eval_text == '-' || *eval_text == '=') - return BADOP; - return MINUS; - case '*': - if (*eval_text == '*') - { - eval_text++; - return EXPONENT; - } - else if (*eval_text == '=') - return BADOP; - return TIMES; - case '/': - if (*eval_text == '=') - return BADOP; - return DIVIDE; - case '%': - if (*eval_text == '=') - return BADOP; - return MODULO; - case '\\': - return RATIO; - case '=': - if (*eval_text == '=') - { - eval_text++; - return EQ; - } - return BADOP; - case '!': - if (*eval_text == '=') - { - eval_text++; - return NOTEQ; - } - return LNOT; - case '>': - if (*eval_text == '=') - { - eval_text++; - return GTEQ; - } - else if (*eval_text == '>') - { - eval_text++; - if (*eval_text == '=') - return BADOP; - else if (*eval_text == '>') - { - eval_text++; - return URSHIFT; - } - return RSHIFT; - } - else - return GT; - case '<': - if (*eval_text == '=') - { - eval_text++; - return LSEQ; - } - else if (*eval_text == '<') - { - if (*++eval_text == '=') - return BADOP; - return LSHIFT; - } - else - return LS; - case '^': - if (*eval_text == '=') - return BADOP; - return XOR; - case '~': - return NOT; - case '&': - if (*eval_text == '&') - { - eval_text++; - return LAND; - } - else if (*eval_text == '=') - return BADOP; - return AND; - case '|': - if (*eval_text == '|') - { - eval_text++; - return LOR; - } - else if (*eval_text == '=') - return BADOP; - return OR; - case '(': - return LEFTP; - case ')': - return RIGHTP; - case '?': - return QUESTION; - case ':': - return COLON; - case ',': - return COMMA; - default: - return ERROR; - } -} - -/* Recursive descent parser. */ -static eval_error -comma_term (m4 *context, eval_token et, number *v1) -{ - number v2; - eval_error er; - - if ((er = condition_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - while ((et = eval_lex (&v2)) == COMMA) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = condition_term (context, et, &v2)) != NO_ERROR) - return er; - numb_set (*v1, v2); - } - numb_fini (v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -condition_term (m4 *context, eval_token et, number *v1) -{ - number v2; - number v3; - eval_error er; - - if ((er = logical_or_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - numb_init (v3); - if ((et = eval_lex (&v2)) == QUESTION) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - /* Implement short-circuiting of valid syntax. */ - er = comma_term (context, et, &v2); - if (er != NO_ERROR - && !(numb_zerop (*v1) && er < SYNTAX_ERROR)) - return er; - - et = eval_lex (&v3); - if (et == ERROR) - return UNKNOWN_INPUT; - if (et != COLON) - return MISSING_COLON; - - et = eval_lex (&v3); - if (et == ERROR) - return UNKNOWN_INPUT; - - er = condition_term (context, et, &v3); - if (er != NO_ERROR - && !(! numb_zerop (*v1) && er < SYNTAX_ERROR)) - return er; - - numb_set (*v1, ! numb_zerop (*v1) ? v2 : v3); - } - numb_fini (v2); - numb_fini (v3); - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -logical_or_term (m4 *context, eval_token et, number *v1) -{ - number v2; - eval_error er; - - if ((er = logical_and_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - while ((et = eval_lex (&v2)) == LOR) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - /* Implement short-circuiting of valid syntax. */ - er = logical_and_term (context, et, &v2); - if (er == NO_ERROR) - numb_lior (*v1, v2); - else if (! numb_zerop (*v1) && er < SYNTAX_ERROR) - numb_set (*v1, numb_ONE); - else - return er; - } - numb_fini (v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -logical_and_term (m4 *context, eval_token et, number *v1) -{ - number v2; - eval_error er; - - if ((er = or_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - while ((et = eval_lex (&v2)) == LAND) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - /* Implement short-circuiting of valid syntax. */ - er = or_term (context, et, &v2); - if (er == NO_ERROR) - numb_land (*v1, v2); - else if (numb_zerop (*v1) && er < SYNTAX_ERROR) - numb_set (*v1, numb_ZERO); - else - return er; - } - numb_fini (v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -or_term (m4 *context, eval_token et, number *v1) -{ - number v2; - eval_error er; - - if ((er = xor_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - while ((et = eval_lex (&v2)) == OR) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = xor_term (context, et, &v2)) != NO_ERROR) - return er; - - numb_ior (context, v1, &v2); - } - numb_fini (v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -xor_term (m4 *context, eval_token et, number *v1) -{ - number v2; - eval_error er; - - if ((er = and_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - while ((et = eval_lex (&v2)) == XOR) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = and_term (context, et, &v2)) != NO_ERROR) - return er; - - numb_eor (context, v1, &v2); - } - numb_fini (v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -and_term (m4 *context, eval_token et, number *v1) -{ - number v2; - eval_error er; - - if ((er = equality_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - while ((et = eval_lex (&v2)) == AND) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = equality_term (context, et, &v2)) != NO_ERROR) - return er; - - numb_and (context, v1, &v2); - } - numb_fini (v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -equality_term (m4 *context, eval_token et, number *v1) -{ - eval_token op; - number v2; - eval_error er; - - if ((er = cmp_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - while ((op = eval_lex (&v2)) == EQ || op == NOTEQ) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = cmp_term (context, et, &v2)) != NO_ERROR) - return er; - - if (op == EQ) - numb_eq (*v1, v2); - else - numb_ne (*v1, v2); - } - numb_fini (v2); - if (op == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -cmp_term (m4 *context, eval_token et, number *v1) -{ - eval_token op; - number v2; - eval_error er; - - if ((er = shift_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - while ((op = eval_lex (&v2)) == GT || op == GTEQ - || op == LS || op == LSEQ) - { - - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = shift_term (context, et, &v2)) != NO_ERROR) - return er; - - switch (op) - { - case GT: - numb_gt (*v1, v2); - break; - - case GTEQ: - numb_ge (*v1, v2); - break; - - case LS: - numb_lt (*v1, v2); - break; - - case LSEQ: - numb_le (*v1, v2); - break; - - default: - assert (!"INTERNAL ERROR: bad comparison operator in cmp_term ()"); - abort (); - } - } - numb_fini (v2); - if (op == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -shift_term (m4 *context, eval_token et, number *v1) -{ - eval_token op; - number v2; - eval_error er; - - if ((er = add_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - while ((op = eval_lex (&v2)) == LSHIFT || op == RSHIFT || op == URSHIFT) - { - - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = add_term (context, et, &v2)) != NO_ERROR) - return er; - - switch (op) - { - case LSHIFT: - numb_lshift (context, v1, &v2); - break; - - case RSHIFT: - numb_rshift (context, v1, &v2); - break; - - case URSHIFT: - numb_urshift (context, v1, &v2); - break; - - default: - assert (!"INTERNAL ERROR: bad shift operator in shift_term ()"); - abort (); - } - } - numb_fini (v2); - if (op == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -add_term (m4 *context, eval_token et, number *v1) -{ - eval_token op; - number v2; - eval_error er; - - if ((er = mult_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - while ((op = eval_lex (&v2)) == PLUS || op == MINUS) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = mult_term (context, et, &v2)) != NO_ERROR) - return er; - - if (op == PLUS) - numb_plus (*v1, v2); - else - numb_minus (*v1, v2); - } - numb_fini (v2); - if (op == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -mult_term (m4 *context, eval_token et, number *v1) -{ - eval_token op; - number v2; - eval_error er; - - if ((er = exp_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - while (op = eval_lex (&v2), - op == TIMES - || op == DIVIDE - || op == MODULO - || op == RATIO) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = exp_term (context, et, &v2)) != NO_ERROR) - return er; - - switch (op) - { - case TIMES: - numb_times (*v1, v2); - break; - - case DIVIDE: - if (numb_zerop (v2)) - return DIVIDE_ZERO; - else - numb_divide(v1, &v2); - break; - - case RATIO: - if (numb_zerop (v2)) - return DIVIDE_ZERO; - else - numb_ratio (*v1, v2); - break; - - case MODULO: - if (numb_zerop (v2)) - return MODULO_ZERO; - else - numb_modulo (context, v1, &v2); - break; - - default: - assert (!"INTERNAL ERROR: bad operator in mult_term ()"); - abort (); - } - } - numb_fini (v2); - if (op == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -exp_term (m4 *context, eval_token et, number *v1) -{ - number v2; - eval_error er; - - if ((er = unary_term (context, et, v1)) != NO_ERROR) - return er; - - numb_init (v2); - while ((et = eval_lex (&v2)) == EXPONENT) - { - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = exp_term (context, et, &v2)) != NO_ERROR) - return er; - - if ((er = numb_pow (v1, &v2)) != NO_ERROR) - return er; - } - numb_fini (v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - eval_undo (); - return NO_ERROR; -} - -static eval_error -unary_term (m4 *context, eval_token et, number *v1) -{ - eval_error er; - - if (et == PLUS || et == MINUS || et == NOT || et == LNOT) - { - eval_token et2 = eval_lex (v1); - if (et2 == ERROR) - return UNKNOWN_INPUT; - - if ((er = unary_term (context, et2, v1)) != NO_ERROR) - return er; - - if (et == MINUS) - numb_negate(*v1); - else if (et == NOT) - numb_not (context, v1); - else if (et == LNOT) - numb_lnot (*v1); - } - else if ((er = simple_term (context, et, v1)) != NO_ERROR) - return er; - - return NO_ERROR; -} - -static eval_error -simple_term (m4 *context, eval_token et, number *v1) -{ - number v2; - eval_error er; - - switch (et) - { - case LEFTP: - et = eval_lex (v1); - if (et == ERROR) - return UNKNOWN_INPUT; - - if ((er = comma_term (context, et, v1)) != NO_ERROR) - return er; - - et = eval_lex (&v2); - if (et == ERROR) - return UNKNOWN_INPUT; - - if (et != RIGHTP) - return MISSING_RIGHT; - - break; - - case NUMBER: - break; - - case BADOP: - return INVALID_OPERATOR; - - default: - return SYNTAX_ERROR; - } - return NO_ERROR; -} - -/* Main entry point, called from "eval" and "mpeval" builtins. */ -void -m4_evaluate (m4 *context, m4_obstack *obs, size_t argc, m4_macro_args *argv) -{ - const m4_call_info *me = m4_arg_info (argv); - const char * str = M4ARG (1); - int radix = 10; - int min = 1; - number val; - eval_token et; - eval_error err = NO_ERROR; - - if (!m4_arg_empty (argv, 2) - && !m4_numeric_arg (context, me, M4ARG (2), M4ARGLEN (2), &radix)) - return; - - if (radix < 1 || radix > 36) - { - m4_warn (context, 0, me, _("radix out of range: %d"), radix); - return; - } - - if (argc >= 4 && !m4_numeric_arg (context, me, M4ARG (3), M4ARGLEN (3), - &min)) - return; - - if (min < 0) - { - m4_warn (context, 0, me, _("negative width: %d"), min); - return; - } - - numb_initialise (); - eval_init_lex (str, M4ARGLEN (1)); - - numb_init (val); - et = eval_lex (&val); - if (et == EOTEXT) - { - m4_warn (context, 0, me, _("empty string treated as 0")); - numb_set (val, numb_ZERO); - } - else - err = comma_term (context, et, &val); - - if (err == NO_ERROR && *eval_text != '\0') - { - if (eval_lex (&val) == BADOP) - err = INVALID_OPERATOR; - else - err = EXCESS_INPUT; - } - - if (err != NO_ERROR) - str = quotearg_style_mem (locale_quoting_style, str, M4ARGLEN (1)); - switch (err) - { - case NO_ERROR: - numb_obstack (obs, val, radix, min); - break; - - case MISSING_RIGHT: - m4_warn (context, 0, me, _("missing right parenthesis: %s"), str); - break; - - case MISSING_COLON: - m4_warn (context, 0, me, _("missing colon: %s"), str); - break; - - case SYNTAX_ERROR: - m4_warn (context, 0, me, _("bad expression: %s"), str); - break; - - case UNKNOWN_INPUT: - m4_warn (context, 0, me, _("bad input: %s"), str); - break; - - case EXCESS_INPUT: - m4_warn (context, 0, me, _("excess input: %s"), str); - break; - - case INVALID_OPERATOR: - m4_warn (context, 0, me, _("invalid operator: %s"), str); - break; - - case DIVIDE_ZERO: - m4_warn (context, 0, me, _("divide by zero: %s"), str); - break; - - case MODULO_ZERO: - m4_warn (context, 0, me, _("modulo by zero: %s"), str); - break; - - case NEGATIVE_EXPONENT: - m4_warn (context, 0, me, _("negative exponent: %s"), str); - break; - - default: - assert (!"INTERNAL ERROR: bad error code in evaluate ()"); - abort (); - } - - numb_fini (val); -} - -static eval_error -numb_pow (number *x, number *y) -{ - /* y should be integral */ - - number ans, yy; - - numb_init (ans); - numb_set_si (&ans, 1); - - if (numb_zerop (*x) && numb_zerop (*y)) - return DIVIDE_ZERO; - - numb_init (yy); - numb_set (yy, *y); - - if (numb_negativep (yy)) - { - numb_negate (yy); - numb_invert (*x); - } - - while (numb_positivep (yy)) - { - numb_times (ans, *x); - numb_decr (yy); - } - numb_set (*x, ans); - - numb_fini (ans); - numb_fini (yy); - return NO_ERROR; -} diff --git a/modules/format.c b/modules/format.c deleted file mode 100644 index 2c87fcc3..00000000 --- a/modules/format.c +++ /dev/null @@ -1,425 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 2001, 2006-2010, 2013-2014, 2017 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 . -*/ - -/* printf like formatting for m4. */ - -#include "vasnprintf.h" - -/* Simple varargs substitute. We assume int and unsigned int are the - same size; likewise for long and unsigned long. We do not yet - handle long double or long long. */ - -/* Parse STR of length LEN as an integer, reporting warnings on behalf - of ME. */ -static int -arg_int (struct m4 *context, const m4_call_info *me, const char *str, - size_t len) -{ - char *endp; - long value; - - /* TODO - also allow parsing `'a' or `"a' which results in the - numeric value of 'a', as in printf(1). */ - if (!len) - { - m4_warn (context, 0, me, _("empty string treated as 0")); - return 0; - } - errno = 0; - value = strtol (str, &endp, 10); - if (endp - str != len) - m4_warn (context, 0, me, _("non-numeric argument %s"), - quotearg_style_mem (locale_quoting_style, str, len)); - else if (isspace (to_uchar (*str))) - m4_warn (context, 0, me, _("leading whitespace ignored")); - else if (errno == ERANGE || (int) value != value) - m4_warn (context, 0, me, _("numeric overflow detected")); - return value; -} - -/* Parse STR of length LEN as a long, reporting warnings on behalf of - ME. */ -static long -arg_long (struct m4 *context, const m4_call_info *me, const char *str, - size_t len) -{ - char *endp; - long value; - - /* TODO - also allow parsing `'a' or `"a' which results in the - numeric value of 'a', as in printf(1). */ - if (!len) - { - m4_warn (context, 0, me, _("empty string treated as 0")); - return 0L; - } - errno = 0; - value = strtol (str, &endp, 10); - if (endp - str != len) - m4_warn (context, 0, me, _("non-numeric argument %s"), - quotearg_style_mem (locale_quoting_style, str, len)); - else if (isspace (to_uchar (*str))) - m4_warn (context, 0, me, _("leading whitespace ignored")); - else if (errno == ERANGE) - m4_warn (context, 0, me, _("numeric overflow detected")); - return value; -} - -/* Check STR of length LEN for embedded NUL, reporting warnings on - behalf of ME. */ -static const char * -arg_string (struct m4 *context, const m4_call_info *me, const char *str, - size_t len) -{ - if (strlen (str) < len) - m4_warn (context, 0, me, _("argument %s truncated"), - quotearg_style_mem (locale_quoting_style, str, len)); - return str; -} - -/* Parse STR of length LEN as a double, reporting warnings on behalf - of ME. */ -static double -arg_double (struct m4 *context, const m4_call_info *me, const char *str, - size_t len) -{ - char *endp; - double value; - - if (!len) - { - m4_warn (context, 0, me, _("empty string treated as 0")); - return 0.0; - } - errno = 0; - value = strtod (str, &endp); - if (endp - str != len) - m4_warn (context, 0, me, _("non-numeric argument %s"), - quotearg_style_mem (locale_quoting_style, str, len)); - else if (isspace (to_uchar (*str))) - m4_warn (context, 0, me, _("leading whitespace ignored")); - else if (errno == ERANGE) - m4_warn (context, 0, me, _("numeric overflow detected")); - return value; -} - -#define ARG_INT(i, argc, argv) \ - ((argc <= ++i) ? 0 : arg_int (context, me, M4ARG (i), M4ARGLEN (i))) - -#define ARG_LONG(i, argc, argv) \ - ((argc <= ++i) ? 0L : arg_long (context, me, M4ARG (i), M4ARGLEN (i))) - -#define ARG_STR(i, argc, argv) \ - ((argc <= ++i) ? "" : arg_string (context, me, M4ARG (i), M4ARGLEN (i))) - -#define ARG_DOUBLE(i, argc, argv) \ - ((argc <= ++i) ? 0.0 : arg_double (context, me, M4ARG (i), M4ARGLEN (i))) - - -/* The main formatting function. Output is placed on the obstack OBS, - the first argument in ARGV is the formatting string, and the rest - is arguments for the string. Warn rather than invoke unspecified - behavior in the underlying printf when we do not recognize a - format. */ - -static void -format (m4 *context, m4_obstack *obs, int argc, m4_macro_args *argv) -{ - const m4_call_info *me = m4_arg_info (argv); - const char *f; /* Format control string. */ - size_t f_len; /* Length of f. */ - const char *fmt; /* Position within f. */ - char fstart[] = "%'+- 0#*.*hhd"; /* Current format spec. */ - char *p; /* Position within fstart. */ - unsigned char c; /* A simple character. */ - int i = 1; /* Index within argc used so far. */ - bool valid_format = true; /* True if entire format string ok. */ - - /* Flags. */ - char flags; /* Flags to use in fstart. */ - enum { - THOUSANDS = 0x01, /* '\''. */ - PLUS = 0x02, /* '+'. */ - MINUS = 0x04, /* '-'. */ - SPACE = 0x08, /* ' '. */ - ZERO = 0x10, /* '0'. */ - ALT = 0x20, /* '#'. */ - DONE = 0x40 /* No more flags. */ - }; - - /* Precision specifiers. */ - int width; /* Minimum field width. */ - int prec; /* Precision. */ - char lflag; /* Long flag. */ - - /* Specifiers we are willing to accept. ok['x'] implies %x is ok. - Various modifiers reduce the set, in order to avoid undefined - behavior in printf. */ - char ok[128]; - - /* Check that formatted text succeeded with correct type. */ - int result = 0; - enum {CHAR, INT, LONG, DOUBLE, STR} datatype; - - f = fmt = M4ARG (1); - f_len = M4ARGLEN (1); - assert (!f[f_len]); /* Requiring a terminating NUL makes parsing simpler. */ - memset (ok, 0, sizeof ok); - while (1) - { - const char *percent = (char *) memchr (fmt, '%', f_len); - if (!percent) - { - obstack_grow (obs, fmt, f_len); - break; - } - obstack_grow (obs, fmt, percent - fmt); - f_len -= percent - fmt + 1; - fmt = percent + 1; - - if (*fmt == '%') - { - obstack_1grow (obs, '%'); - fmt++; - f_len--; - continue; - } - - p = fstart + 1; /* % */ - lflag = 0; - ok['a'] = ok['A'] = ok['c'] = ok['d'] = ok['e'] = ok['E'] - = ok['f'] = ok['F'] = ok['g'] = ok['G'] = ok['i'] = ok['o'] - = ok['s'] = ok['u'] = ok['x'] = ok['X'] = 1; - - /* Parse flags. */ - flags = 0; - do - { - switch (*fmt) - { - case '\'': /* thousands separator */ - ok['a'] = ok['A'] = ok['c'] = ok['e'] = ok['E'] - = ok['o'] = ok['s'] = ok['x'] = ok['X'] = 0; - flags |= THOUSANDS; - break; - - case '+': /* mandatory sign */ - ok['c'] = ok['o'] = ok['s'] = ok['u'] = ok['x'] = ok['X'] = 0; - flags |= PLUS; - break; - - case ' ': /* space instead of positive sign */ - ok['c'] = ok['o'] = ok['s'] = ok['u'] = ok['x'] = ok['X'] = 0; - flags |= SPACE; - break; - - case '0': /* zero padding */ - ok['c'] = ok['s'] = 0; - flags |= ZERO; - break; - - case '#': /* alternate output */ - ok['c'] = ok['d'] = ok['i'] = ok['s'] = ok['u'] = 0; - flags |= ALT; - break; - - case '-': /* left justification */ - flags |= MINUS; - break; - - default: - flags |= DONE; - break; - } - } - while (!(flags & DONE) && (f_len--, fmt++)); - if (flags & THOUSANDS) - *p++ = '\''; - if (flags & PLUS) - *p++ = '+'; - if (flags & MINUS) - *p++ = '-'; - if (flags & SPACE) - *p++ = ' '; - if (flags & ZERO) - *p++ = '0'; - if (flags & ALT) - *p++ = '#'; - - /* Minimum field width; an explicit 0 is the same as not giving - the width. */ - width = 0; - *p++ = '*'; - if (*fmt == '*') - { - width = ARG_INT (i, argc, argv); - fmt++; - f_len--; - } - else - while (isdigit ((unsigned char) *fmt)) - { - width = 10 * width + *fmt - '0'; - fmt++; - f_len--; - } - - /* Maximum precision; an explicit negative precision is the same - as not giving the precision. A lone '.' is a precision of 0. */ - prec = -1; - *p++ = '.'; - *p++ = '*'; - if (*fmt == '.') - { - ok['c'] = 0; - f_len--; - if (*(++fmt) == '*') - { - prec = ARG_INT (i, argc, argv); - ++fmt; - f_len--; - } - else - { - prec = 0; - while (isdigit ((unsigned char) *fmt)) - { - prec = 10 * prec + *fmt - '0'; - fmt++; - f_len--; - } - } - } - - /* Length modifiers. We don't yet recognize ll, j, t, or z. */ - if (*fmt == 'l') - { - *p++ = 'l'; - lflag = 1; - fmt++; - f_len--; - ok['c'] = ok['s'] = 0; - } - else if (*fmt == 'h') - { - *p++ = 'h'; - fmt++; - f_len--; - if (*fmt == 'h') - { - *p++ = 'h'; - fmt++; - f_len--; - } - ok['a'] = ok['A'] = ok['c'] = ok['e'] = ok['E'] = ok['f'] = ok['F'] - = ok['g'] = ok['G'] = ok['s'] = 0; - } - - c = *fmt; - if (sizeof ok <= c || !ok[c] || !f_len) - { - m4_warn (context, 0, me, _("unrecognized specifier in %s"), - quotearg_style_mem (locale_quoting_style, f, M4ARGLEN (1))); - valid_format = false; - if (f_len > 0) - { - fmt++; - f_len--; - } - continue; - } - fmt++; - f_len--; - - /* Specifiers. We don't yet recognize C, S, n, or p. */ - switch (c) - { - case 'c': - datatype = CHAR; - p -= 2; /* %.*c is undefined, so undo the '.*'. */ - break; - - case 's': - datatype = STR; - break; - - case 'd': - case 'i': - case 'o': - case 'x': - case 'X': - case 'u': - datatype = lflag ? LONG : INT; - break; - - case 'a': - case 'A': - case 'e': - case 'E': - case 'f': - case 'F': - case 'g': - case 'G': - datatype = DOUBLE; - break; - - default: - abort (); - } - *p++ = c; - *p = '\0'; - - switch (datatype) - { - case CHAR: - result = obstack_printf (obs, fstart, width, - ARG_INT (i, argc, argv)); - break; - - case INT: - result = obstack_printf (obs, fstart, width, prec, - ARG_INT (i, argc, argv)); - break; - - case LONG: - result = obstack_printf (obs, fstart, width, prec, - ARG_LONG (i, argc, argv)); - break; - - case DOUBLE: - result = obstack_printf (obs, fstart, width, prec, - ARG_DOUBLE (i, argc, argv)); - break; - - case STR: - result = obstack_printf (obs, fstart, width, prec, - ARG_STR (i, argc, argv)); - break; - - default: - abort (); - } - /* Since obstack_printf can only fail with EILSEQ or EINVAL, but - we constructed fstart, the result should not be negative. */ - assert (0 <= result); - } - if (valid_format) - m4_bad_argc (context, argc, me, i, i, true); -} diff --git a/modules/gnu.c b/modules/gnu.c deleted file mode 100644 index 334ab67d..00000000 --- a/modules/gnu.c +++ /dev/null @@ -1,1077 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 2000, 2004-2010, 2013-2014, 2017 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 . -*/ - -#include - -/* Build using only the exported interfaces, unles NDEBUG is set, in - which case use private symbols to speed things up as much as possible. */ -#ifndef NDEBUG -# include -#else -# include "m4private.h" -#endif - -#include "modules/m4.h" -#include "quotearg.h" -#include "spawn-pipe.h" -#include "wait-process.h" - -/* Maintain each of the builtins implemented in this modules along - with their details in a single table for easy maintenance. - - function macros blind side minargs maxargs */ -#define builtin_functions \ - BUILTIN (__file__, false, false, false, 0, 0 ) \ - BUILTIN (__line__, false, false, false, 0, 0 ) \ - BUILTIN (__program__, false, false, false, 0, 0 ) \ - BUILTIN (builtin, true, true, false, 1, -1 ) \ - BUILTIN (changeresyntax,false,true, false, 1, 1 ) \ - BUILTIN (changesyntax,false, true, false, 1, -1 ) \ - BUILTIN (debugfile, false, false, false, 0, 1 ) \ - BUILTIN (debuglen, false, true, false, 1, 1 ) \ - BUILTIN (debugmode, false, false, false, 0, 1 ) \ - BUILTIN (esyscmd, false, true, true, 1, 1 ) \ - BUILTIN (format, false, true, false, 1, -1 ) \ - BUILTIN (indir, true, true, false, 1, -1 ) \ - BUILTIN (mkdtemp, false, true, false, 1, 1 ) \ - BUILTIN (patsubst, false, true, true, 2, 4 ) \ - BUILTIN (regexp, false, true, true, 2, 4 ) \ - BUILTIN (renamesyms, false, true, false, 2, 3 ) \ - BUILTIN (m4modules, false, false, false, 0, 0 ) \ - BUILTIN (m4symbols, true, false, false, 0, -1 ) \ - BUILTIN (syncoutput, false, true, false, 1, 1 ) \ - - -/* Generate prototypes for each builtin handler function. */ -#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN (handler) - builtin_functions -#undef BUILTIN - - -/* Generate a table for mapping m4 symbol names to handler functions. */ -static const m4_builtin m4_builtin_table[] = -{ -#define BUILTIN(handler, macros, blind, side, min, max) \ - M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max) - - builtin_functions -#undef BUILTIN - - { NULL, NULL, 0, 0, 0 }, -}; - - -/* A table for mapping m4 symbol names to simple expansion text. */ -static const m4_macro m4_macro_table[] = -{ - /* name text min max */ -#if UNIX - { "__unix__", "", 0, 0 }, -#endif -#if W32_NATIVE - { "__windows__", "", 0, 0 }, -#endif -#if OS2 - { "__os2__", "", 0, 0 }, -#endif - { "__gnu__", "", 0, 0 }, - { "__m4_version__", VERSION,0, 0 }, - - { NULL, NULL, 0, 0 }, -}; - - -void -include_gnu (m4 *context, m4_module *module, m4_obstack *obs) -{ - m4_install_builtins (context, module, m4_builtin_table); - m4_install_macros (context, module, m4_macro_table); -} - - - -/* Regular expressions. Reuse re_registers among multiple - re_pattern_buffer allocations to reduce malloc usage. */ - -/* Maybe this is worth making runtime tunable. Too small, and nothing - gets cached because the working set of active regex is larger than - the cache, and we are always swapping out entries. Too large, and - the time spent searching the cache for a match overtakes the time - saved by caching. For now, this size proved reasonable for the - typical working set of Autoconf 2.62. */ -#define REGEX_CACHE_SIZE 16 - -/* Structure for using a compiled regex, as well as making it easier - to cache frequently used expressions. */ -typedef struct { - unsigned count; /* usage counter */ - int resyntax; /* flavor of regex */ - size_t len; /* length of string */ - char *str; /* copy of compiled string */ - struct re_pattern_buffer *pat; /* compiled regex, allocated */ - struct re_registers regs; /* match registers, reused */ -} m4_pattern_buffer; - -/* Storage for the cache of regular expressions. */ -static m4_pattern_buffer regex_cache[REGEX_CACHE_SIZE]; - -/* Compile a REGEXP of length LEN using the RESYNTAX flavor, and - return the buffer. On error, report the problem on behalf of - CALLER, and return NULL. */ - -static m4_pattern_buffer * -regexp_compile (m4 *context, const m4_call_info *caller, const char *regexp, - size_t len, int resyntax) -{ - /* regex_cache is guaranteed to start life 0-initialized, which - works in the algorithm below. - - FIXME - this method is not reentrant, since re_compile_pattern - mallocs memory, depends on the global variable re_syntax_options - for its syntax (but at least the compiled regex remembers its - syntax even if the global variable changes later), and since we - use a static variable. To be reentrant, we would need a mutex in - this method, and move the storage for regex_cache into context. */ - - const char *msg; /* error message from re_compile_pattern */ - int i; /* iterator */ - m4_pattern_buffer *victim; /* cache slot to replace */ - unsigned victim_count; /* track which victim to replace */ - struct re_pattern_buffer *pat;/* newly compiled regex */ - - /* First, check if REGEXP is already cached with the given RESYNTAX. - If so, increase its use count and return it. */ - for (i = 0; i < REGEX_CACHE_SIZE; i++) - if (len == regex_cache[i].len && resyntax == regex_cache[i].resyntax - && regex_cache[i].str && memcmp (regexp, regex_cache[i].str, len) == 0) - { - regex_cache[i].count++; - return ®ex_cache[i]; - } - - /* Next, check if REGEXP can be compiled. */ - pat = (struct re_pattern_buffer *) xzalloc (sizeof *pat); - re_set_syntax (resyntax); - msg = re_compile_pattern (regexp, len, pat); - - if (msg != NULL) - { - m4_warn (context, 0, caller, _("bad regular expression %s: %s"), - quotearg_style_mem (locale_quoting_style, regexp, len), msg); - regfree (pat); - free (pat); - return NULL; - } - /* Use a fastmap for speed; it is freed by regfree. */ - pat->fastmap = xcharalloc (UCHAR_MAX + 1); - - /* Now, find a victim slot. Decrease the count of all entries, then - prime the count of the victim slot at REGEX_CACHE_SIZE. This - way, frequently used entries and newly created entries are least - likely to be victims next time we have a cache miss. */ - victim = regex_cache; - victim_count = victim->count; - if (victim_count) - victim->count--; - for (i = 1; i < REGEX_CACHE_SIZE; i++) - { - if (regex_cache[i].count < victim_count) - { - victim_count = regex_cache[i].count; - victim = ®ex_cache[i]; - } - if (regex_cache[i].count) - regex_cache[i].count--; - } - victim->count = REGEX_CACHE_SIZE; - victim->resyntax = resyntax; - victim->len = len; - if (victim->str) - { - free (victim->str); - regfree (victim->pat); - free (victim->pat); - } - victim->str = xstrdup (regexp); - victim->pat = pat; - re_set_registers (pat, &victim->regs, victim->regs.num_regs, - victim->regs.start, victim->regs.end); - return victim; -} - - -/* Wrap up GNU Regex re_search call to work with an m4_pattern_buffer. - If NO_SUB, then storing matches in buf->regs is not necessary. */ - -static regoff_t -regexp_search (m4_pattern_buffer *buf, const char *string, const int size, - const int start, const int range, bool no_sub) -{ - return re_search (buf->pat, string, size, start, range, - no_sub ? NULL : &buf->regs); -} - - -/* Function to perform substitution by regular expressions. Used by - the builtins regexp, patsubst and renamesyms. The changed text is - placed on the obstack OBS. The substitution is REPL of length - REPL_LEN, with \& substituted by this part of VICTIM matched by the - last whole regular expression, and \N substituted by the text - matched by the Nth parenthesized sub-expression in BUF. Any - warnings are issued on behalf of CALLER. BUF may be NULL for the - empty regex. */ - -static void -substitute (m4 *context, m4_obstack *obs, const m4_call_info *caller, - const char *victim, const char *repl, size_t repl_len, - m4_pattern_buffer *buf) -{ - int ch; - while (1) - { - const char *backslash = (char *) memchr (repl, '\\', repl_len); - if (!backslash) - { - obstack_grow (obs, repl, repl_len); - return; - } - obstack_grow (obs, repl, backslash - repl); - repl_len -= backslash - repl + 1; - if (!repl_len) - { - m4_warn (context, 0, caller, - _("trailing \\ ignored in replacement")); - return; - } - repl = backslash + 1; - ch = *repl++; - repl_len--; - switch (ch) - { - case '&': - if (buf) - obstack_grow (obs, victim + buf->regs.start[0], - buf->regs.end[0] - buf->regs.start[0]); - break; - - case '1': case '2': case '3': case '4': case '5': case '6': - case '7': case '8': case '9': - ch -= '0'; - if (!buf || buf->pat->re_nsub < ch) - m4_warn (context, 0, caller, _("sub-expression %d not present"), - ch); - else if (buf->regs.end[ch] > 0) - obstack_grow (obs, victim + buf->regs.start[ch], - buf->regs.end[ch] - buf->regs.start[ch]); - break; - - default: - obstack_1grow (obs, ch); - break; - } - } -} - - -/* For each match against REGEXP of length REGEXP_LEN (precompiled in - BUF as returned by regexp_compile) in VICTIM of length LEN, - substitute REPLACE of length REPL_LEN. Non-matching characters are - copied verbatim, and the result copied to the obstack. Errors are - reported on behalf of CALLER. Return true if a substitution was - made. If OPTIMIZE is set, don't worry about copying the input if - no changes are made. */ - -static bool -regexp_substitute (m4 *context, m4_obstack *obs, const m4_call_info *caller, - const char *victim, size_t len, const char *regexp, - size_t regexp_len, m4_pattern_buffer *buf, - const char *replace, size_t repl_len, bool optimize) -{ - regoff_t matchpos = 0; /* start position of match */ - size_t offset = 0; /* current match offset */ - bool subst = !optimize; /* if a substitution has been made */ - - while (offset <= len) - { - matchpos = regexp_search (buf, victim, len, offset, len - offset, - false); - - if (matchpos < 0) - { - - /* Match failed -- either error or there is no match in the - rest of the string, in which case the rest of the string is - copied verbatim. */ - - if (matchpos == -2) - m4_error (context, 0, 0, caller, - _("problem matching regular expression %s"), - quotearg_style_mem (locale_quoting_style, regexp, - regexp_len)); - else if (offset < len && subst) - obstack_grow (obs, victim + offset, len - offset); - break; - } - - /* Copy the part of the string that was skipped by re_search (). */ - - if (matchpos > offset) - obstack_grow (obs, victim + offset, matchpos - offset); - - /* Handle the part of the string that was covered by the match. */ - - substitute (context, obs, caller, victim, replace, repl_len, buf); - subst = true; - - /* Update the offset to the end of the match. If the regexp - matched a null string, advance offset one more, to avoid - infinite loops. */ - - offset = buf->regs.end[0]; - if (buf->regs.start[0] == buf->regs.end[0]) - { - if (offset < len) - obstack_1grow (obs, victim[offset]); - offset++; - } - } - - return subst; -} - - - -/** - * __file__ - **/ -M4BUILTIN_HANDLER (__file__) -{ - m4_shipout_string (context, obs, m4_get_current_file (context), SIZE_MAX, - true); -} - - -/** - * __line__ - **/ -M4BUILTIN_HANDLER (__line__) -{ - m4_shipout_int (obs, m4_get_current_line (context)); -} - - -/** - * __program__ - **/ -M4BUILTIN_HANDLER (__program__) -{ - m4_shipout_string (context, obs, m4_get_program_name (), SIZE_MAX, true); -} - - -/* The builtin "builtin" allows calls to builtin macros, even if their - definition has been overridden or shadowed. It is thus possible to - redefine builtins, and still access their original definition. A - special form allows one to retrieve the special token that defn - would normally return, even if that builtin is not currently - defined and hence can't be passed to defn. */ - -/** - * builtin(MACRO, [...]) - * builtin(defn(`builtin'), MACRO) - **/ -M4BUILTIN_HANDLER (builtin) -{ - const m4_call_info *me = m4_arg_info (argv); - const char *name; - size_t len; - m4_symbol_value *value = NULL; - - if (!m4_is_arg_text (argv, 1)) - { - assert (m4_is_arg_func (argv, 1)); - if (m4_arg_func (argv, 1) == builtin_builtin) - { - if (m4_bad_argc (context, argc, me, 2, 2, false)) - return; - if (!m4_is_arg_text (argv, 2)) - { - m4_warn (context, 0, me, _("invalid macro name ignored")); - return; - } - name = M4ARG (2); - len = M4ARGLEN (2); - if (len == strlen (name)) - value = m4_builtin_find_by_name (context, NULL, name); - if (value) - { - m4_push_builtin (context, obs, value); - free (value); - } - else if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF)) - m4_warn (context, 0, me, _("undefined builtin %s"), - quotearg_style_mem (locale_quoting_style, name, len)); - } - else - m4_warn (context, 0, me, _("invalid macro name ignored")); - } - else - { - name = M4ARG (1); - len = M4ARGLEN (1); - if (len == strlen (name)) - value = m4_builtin_find_by_name (context, NULL, name); - if (value == NULL) - { - if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF)) - m4_warn (context, 0, me, _("undefined builtin %s"), - quotearg_style_mem (locale_quoting_style, name, len)); - } - else - { - const m4_builtin *bp = m4_get_symbol_value_builtin (value); - m4_macro_args *new_argv; - bool flatten = (bp->flags & M4_BUILTIN_FLATTEN_ARGS) != 0; - new_argv = m4_make_argv_ref (context, argv, name, len, flatten, - false); - if (!m4_bad_argc (context, argc - 1, m4_arg_info (new_argv), - bp->min_args, bp->max_args, - (bp->flags & M4_BUILTIN_SIDE_EFFECT) != 0)) - bp->func (context, obs, argc - 1, new_argv); - free (value); - } - } -} - - -/* Change the current regexp syntax to SPEC of length LEN, or report - failure on behalf of CALLER. Currently this affects the builtins: - `patsubst', `regexp' and `renamesyms'. */ - -static int -m4_resyntax_encode_safe (m4 *context, const m4_call_info *caller, - const char *spec, size_t len) -{ - int resyntax; - - if (strlen (spec) < len) - resyntax = -1; - else - resyntax = m4_regexp_syntax_encode (spec); - - if (resyntax < 0) - m4_warn (context, 0, caller, _("bad syntax-spec: %s"), - quotearg_style_mem (locale_quoting_style, spec, len)); - - return resyntax; -} - - -/** - * changeresyntax(RESYNTAX-SPEC) - **/ -M4BUILTIN_HANDLER (changeresyntax) -{ - int resyntax = m4_resyntax_encode_safe (context, m4_arg_info (argv), - M4ARG (1), M4ARGLEN (1)); - - if (resyntax >= 0) - m4_set_regexp_syntax_opt (context, resyntax); -} - - -/* Change the current input syntax. The function m4_set_syntax () - lives in syntax.c. Any changes to comment delimiters and quotes - made here will be overridden by a call to `changecom' or - `changequote'. */ - -/** - * changesyntax(SYNTAX-SPEC, ...) - **/ -M4BUILTIN_HANDLER (changesyntax) -{ - const m4_call_info *me = m4_arg_info (argv); - M4_MODULE_IMPORT (m4, m4_expand_ranges); - - if (m4_expand_ranges) - { - size_t i; - for (i = 1; i < argc; i++) - { - size_t len = M4ARGLEN (i); - const char *spec; - char key; - char action; - - if (!len) - { - m4_reset_syntax (M4SYNTAX); - continue; - } - spec = M4ARG (i); - key = *spec++; - len--; - action = len ? *spec : '\0'; - switch (action) - { - case '-': - case '+': - case '=': - spec++; - len--; - break; - case '\0': - if (!len) - break; - /* fall through */ - default: - action = '='; - break; - } - if (len) - spec = m4_expand_ranges (spec, &len, m4_arg_scratch (context)); - if (m4_set_syntax (M4SYNTAX, key, action, spec, len) < 0) - m4_warn (context, 0, me, _("undefined syntax code: %s"), - quotearg_style_mem (locale_quoting_style, &key, 1)); - } - } - else - assert (!"Unable to import from m4 module"); -} - - -/* Specify the destination of the debugging output. With one argument, the - argument is taken as a file name, with no arguments, revert to stderr. */ - -/** - * debugfile([FILENAME]) - **/ -M4BUILTIN_HANDLER (debugfile) -{ - const m4_call_info *me = m4_arg_info (argv); - - if (argc == 1) - m4_debug_set_output (context, me, NULL); - else if (m4_get_safer_opt (context) && !m4_arg_empty (argv, 1)) - m4_error (context, 0, 0, me, _("disabled by --safer")); - else - { - const char *str = M4ARG (1); - size_t len = M4ARGLEN (1); - if (strlen (str) < len) - m4_warn (context, 0, me, _("argument %s truncated"), - quotearg_style_mem (locale_quoting_style, str, len)); - if (!m4_debug_set_output (context, me, str)) - m4_warn (context, errno, me, _("cannot set debug file %s"), - quotearg_style (locale_quoting_style, str)); - } -} - - -/* On-the-fly control of debug length. It takes one integer - argument. */ - -/** - * debuglen(LEN) - **/ -M4BUILTIN_HANDLER (debuglen) -{ - int i; - size_t s; - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), - &i)) - return; - /* FIXME - make m4_numeric_arg more powerful - we want to accept - suffixes, and limit the result to size_t. */ - s = i <= 0 ? SIZE_MAX : i; - m4_set_max_debug_arg_length_opt (context, s); -} - -/* On-the-fly control of the format of the tracing output. It takes one - argument, which is a character string like given to the -d option, or - none in which case the debug_level is zeroed. */ - -/** - * debugmode([FLAGS]) - **/ -M4BUILTIN_HANDLER (debugmode) -{ - const char* mode = M4ARG (1); - size_t len = M4ARGLEN (1); - if (argc == 1) - m4_set_debug_level_opt (context, 0); - else if (m4_debug_decode (context, mode, len) < 0) - m4_warn (context, 0, m4_arg_info (argv), - _("bad debug flags: %s"), - quotearg_style_mem (locale_quoting_style, mode, len)); -} - - -/* Same as the sysymd builtin from m4.c module, but expand to the - output of SHELL-COMMAND. */ - -/** - * esyscmd(SHELL-COMMAND) - **/ - -M4BUILTIN_HANDLER (esyscmd) -{ - const m4_call_info *me = m4_arg_info (argv); - const char *cmd = M4ARG (1); - size_t len = M4ARGLEN (1); - M4_MODULE_IMPORT (m4, m4_set_sysval); - M4_MODULE_IMPORT (m4, m4_sysval_flush); - - if (m4_set_sysval && m4_sysval_flush) - { - pid_t child; - int fd; - FILE *pin; - int status; - int sig_status; - const char *prog_args[4] = { "sh", "-c" }; - const char *caller; - - if (m4_get_safer_opt (context)) - { - m4_error (context, 0, 0, me, _("disabled by --safer")); - return; - } - if (strlen (cmd) != len) - m4_warn (context, 0, me, _("argument %s truncated"), - quotearg_style_mem (locale_quoting_style, cmd, len)); - - /* Optimize the empty command. */ - if (!*cmd) - { - m4_set_sysval (0); - return; - } - - m4_sysval_flush (context, false); -#if W32_NATIVE - if (strstr (M4_SYSCMD_SHELL, "cmd")) - { - prog_args[0] = "cmd"; - prog_args[1] = "/c"; - } -#endif - prog_args[2] = cmd; - caller = m4_info_name (me); - errno = 0; - child = create_pipe_in (caller, M4_SYSCMD_SHELL, (char **) prog_args, - NULL, false, true, false, &fd); - if (child == -1) - { - m4_error (context, 0, errno, me, _("cannot run command %s"), - quotearg_style (locale_quoting_style, cmd)); - m4_set_sysval (127); - return; - } -#if OS2 - /* On OS/2 kLIBC, fdopen() creates a stream in a mode of a file - descriptor. So incldue "t" to open stream in a text mode explicitly. */ - pin = fdopen (fd, "rt"); -#else - pin = fdopen (fd, "r"); -#endif - if (!pin) - { - m4_error (context, 0, errno, me, _("cannot run command %s"), - quotearg_style (locale_quoting_style, cmd)); - m4_set_sysval (127); - close (fd); - return; - } - while (1) - { - size_t avail = obstack_room (obs); - if (!avail) - { - int ch = getc (pin); - if (ch == EOF) - break; - obstack_1grow (obs, ch); - } - else - { - size_t len = fread (obstack_next_free (obs), 1, avail, pin); - if (len <= 0) - break; - obstack_blank_fast (obs, len); - } - } - if (ferror (pin) || fclose (pin)) - m4_error (context, EXIT_FAILURE, errno, me, - _("cannot read pipe to command %s"), - quotearg_style (locale_quoting_style, cmd)); - errno = 0; - status = wait_subprocess (child, caller, false, true, true, false, - &sig_status); - if (sig_status) - { - assert (status == 127); - m4_set_sysval (sig_status << 8); - } - else - { - if (status == 127 && errno) - m4_error (context, 0, errno, me, _("cannot run command %s"), - quotearg_style (locale_quoting_style, cmd)); - m4_set_sysval (status); - } - } - else - assert (!"Unable to import from m4 module"); -} - - -/* Frontend for printf like formatting. The function format () lives in - the file format.c. */ - -#include "format.c" - -/** - * format(FORMAT-STRING, [...]) - **/ -M4BUILTIN_HANDLER (format) -{ - format (context, obs, argc, argv); -} - - -/* The builtin "indir" allows indirect calls to macros, even if their name - is not a proper macro name. It is thus possible to define macros with - ill-formed names for internal use in larger macro packages. */ - -/** - * indir(MACRO, [...]) - **/ -M4BUILTIN_HANDLER (indir) -{ - const m4_call_info *me = m4_arg_info (argv); - if (!m4_is_arg_text (argv, 1)) - m4_warn (context, 0, me, _("invalid macro name ignored")); - else - { - const char *name = M4ARG (1); - size_t len = M4ARGLEN (1); - m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, name, len); - - if (symbol == NULL) - { - if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF)) - m4_warn (context, 0, me, _("undefined macro %s"), - quotearg_style_mem (locale_quoting_style, name, len)); - } - else - { - m4_macro_args *new_argv; - m4_symbol_value *value = m4_get_symbol_value (symbol); - new_argv = m4_make_argv_ref (context, argv, name, len, - m4_symbol_flatten_args (symbol), - m4_get_symbol_traced (symbol)); - m4_trace_prepare (context, m4_arg_info (new_argv), value); - m4_macro_call (context, value, obs, new_argv); - } - } -} - - -/* The builtin "mkdtemp" allows creation of temporary directories. */ - -/** - * mkdtemp(TEMPLATE) - **/ -M4BUILTIN_HANDLER (mkdtemp) -{ - M4_MODULE_IMPORT (m4, m4_make_temp); - - if (m4_make_temp) - m4_make_temp (context, obs, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), - true); - else - assert (!"Unable to import from m4 module"); -} - - -/* Substitute all matches of a regexp occurring in a string. Each - match of the second argument (a regexp) in the first argument is - changed to the optional third argument, with \& substituted by the - matched text, and \N substituted by the text matched by the Nth - parenthesized sub-expression. The optional fourth argument changes - the regex flavor. */ - -/** - * patsubst(VICTIM, REGEXP, [REPLACEMENT], [RESYNTAX]) - **/ -M4BUILTIN_HANDLER (patsubst) -{ - const m4_call_info *me = m4_arg_info (argv); - const char *pattern; /* regular expression */ - const char *replace; /* replacement */ - m4_pattern_buffer *buf; /* compiled regular expression */ - int resyntax; - - resyntax = m4_get_regexp_syntax_opt (context); - if (argc >= 5) /* additional args ignored */ - { - resyntax = m4_resyntax_encode_safe (context, me, M4ARG (4), - M4ARGLEN (4)); - if (resyntax < 0) - return; - } - - /* The empty regex matches everywhere, but if there is no - replacement, we need not waste time with it. */ - if (m4_arg_empty (argv, 2) && m4_arg_empty (argv, 3)) - { - m4_push_arg (context, obs, argv, 1); - return; - } - - pattern = M4ARG (2); - replace = M4ARG (3); - - buf = regexp_compile (context, me, pattern, M4ARGLEN (2), resyntax); - if (!buf) - return; - - regexp_substitute (context, obs, me, M4ARG (1), M4ARGLEN (1), pattern, - M4ARGLEN (2), buf, replace, M4ARGLEN (3), false); -} - - -/* Regular expression version of index. Given two arguments, expand - to the index of the first match of the second argument (a regexp) - in the first. Expand to -1 if there is no match. Given a third - argument, a match is substituted according to this argument. The - optional fourth argument changes the regex flavor. */ - -/** - * regexp(VICTIM, REGEXP, RESYNTAX) - * regexp(VICTIM, REGEXP, [REPLACEMENT], [RESYNTAX]) - **/ -M4BUILTIN_HANDLER (regexp) -{ - const m4_call_info *me = m4_arg_info (argv); - const char *victim; /* string to search */ - const char *pattern; /* regular expression */ - const char *replace; /* optional replacement string */ - m4_pattern_buffer *buf; /* compiled regular expression */ - regoff_t startpos; /* start position of match */ - size_t len; /* length of first argument */ - int resyntax; - - pattern = M4ARG (2); - replace = M4ARG (3); - resyntax = m4_get_regexp_syntax_opt (context); - - if (argc == 4) - { - resyntax = m4_regexp_syntax_encode (replace); - - /* The first case is the most difficult, because the empty string - is a valid RESYNTAX, yet we want `regexp(aab, a*, )' to return - an empty string as per M4 1.4.x. */ - - if (m4_arg_empty (argv, 3) || (resyntax < 0)) - /* regexp(VICTIM, REGEXP, REPLACEMENT) */ - resyntax = m4_get_regexp_syntax_opt (context); - else - /* regexp(VICTIM, REGEXP, RESYNTAX) */ - replace = NULL; - } - else if (argc >= 5) - { - /* regexp(VICTIM, REGEXP, REPLACEMENT, RESYNTAX) */ - resyntax = m4_resyntax_encode_safe (context, me, M4ARG (4), - M4ARGLEN (4)); - if (resyntax < 0) - return; - } - else - /* regexp(VICTIM, REGEXP) */ - replace = NULL; - - if (m4_arg_empty (argv, 2)) - { - /* The empty regex matches everything. */ - if (replace) - substitute (context, obs, me, M4ARG (1), replace, M4ARGLEN (3), NULL); - else - m4_shipout_int (obs, 0); - return; - } - - buf = regexp_compile (context, me, pattern, M4ARGLEN (2), resyntax); - if (!buf) - return; - - victim = M4ARG (1); - len = M4ARGLEN (1); - startpos = regexp_search (buf, victim, len, 0, len, replace == NULL); - - if (startpos == -2) - { - m4_error (context, 0, 0, me, _("problem matching regular expression %s"), - quotearg_style_mem (locale_quoting_style, pattern, - M4ARGLEN (2))); - return; - } - - if (replace == NULL) - m4_shipout_int (obs, startpos); - else if (startpos >= 0) - substitute (context, obs, me, victim, replace, M4ARGLEN (3), buf); -} - - -/* Rename all current symbols that match REGEXP according to the - REPLACEMENT specification. */ - -/** - * renamesyms(REGEXP, REPLACEMENT, [RESYNTAX]) - **/ -M4BUILTIN_HANDLER (renamesyms) -{ - M4_MODULE_IMPORT (m4, m4_dump_symbols); - - if (m4_dump_symbols) - { - const m4_call_info *me = m4_arg_info (argv); - const char *regexp; /* regular expression string */ - size_t regexp_len; - const char *replace; /* replacement expression string */ - size_t replace_len; - - m4_pattern_buffer *buf; /* compiled regular expression */ - - m4_dump_symbol_data data; - - int resyntax; - - regexp = M4ARG (1); - regexp_len = M4ARGLEN (1); - replace = M4ARG (2); - replace_len = M4ARGLEN (2); - - resyntax = m4_get_regexp_syntax_opt (context); - if (argc >= 4) - { - resyntax = m4_resyntax_encode_safe (context, me, M4ARG (3), - M4ARGLEN (3)); - if (resyntax < 0) - return; - } - - buf = regexp_compile (context, me, regexp, regexp_len, resyntax); - if (!buf) - return; - - data.obs = m4_arg_scratch (context); - m4_dump_symbols (context, &data, 1, argv, false); - - for (; data.size > 0; --data.size, data.base++) - { - const m4_string *key = &data.base[0]; - - if (regexp_substitute (context, data.obs, me, key->str, key->len, - regexp, regexp_len, buf, replace, replace_len, - true)) - { - size_t newlen = obstack_object_size (data.obs); - m4_symbol_rename (M4SYMTAB, key->str, key->len, - (char *) obstack_finish (data.obs), newlen); - } - } - } - else - assert (!"Unable to import from m4 module"); -} - - -/** - * m4modules() - **/ -M4BUILTIN_HANDLER (m4modules) -{ - /* The expansion of this builtin is a comma separated list of - loaded modules. */ - m4_module *module = m4_module_next (context, NULL); - - if (module) - do - { - m4_shipout_string (context, obs, m4_get_module_name (module), SIZE_MAX, - true); - - if ((module = m4_module_next (context, module))) - obstack_1grow (obs, ','); - } - while (module); -} - - -/* Implementation of "m4symbols". It builds up a table of pointers to - symbols, sorts it and ships out the symbol names. */ - -/** - * m4symbols([...]) - **/ -M4BUILTIN_HANDLER (m4symbols) -{ - M4_MODULE_IMPORT (m4, m4_dump_symbols); - - if (m4_dump_symbols) - { - m4_dump_symbol_data data; - - data.obs = m4_arg_scratch (context); - m4_dump_symbols (context, &data, argc, argv, false); - - for (; data.size > 0; --data.size, data.base++) - { - m4_shipout_string (context, obs, data.base->str, data.base->len, - true); - if (data.size > 1) - obstack_1grow (obs, ','); - } - } - else - assert (!"Unable to import from m4 module"); -} - - -/* This contains macro which implements syncoutput() which takes one arg - 1, on, yes - turn on sync lines - 0, off, no, blank - turn off sync lines - everything else is silently ignored */ - -/** - * syncoutput(TRUTH) - **/ -M4BUILTIN_HANDLER (syncoutput) -{ - bool value = m4_get_syncoutput_opt (context); - value = m4_parse_truth_arg (context, m4_arg_info (argv), M4ARG (1), - M4ARGLEN (1), value); - m4_set_syncoutput_opt (context, value); -} diff --git a/modules/m4.c b/modules/m4.c deleted file mode 100644 index ed06942b..00000000 --- a/modules/m4.c +++ /dev/null @@ -1,1324 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 2000, 2002-2004, 2006-2010, 2013-2014, 2017 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 . -*/ - -#include - -/* Build using only the exported interfaces, unless NDEBUG is set, in - which case use private symbols to speed things up as much as possible. */ -#ifndef NDEBUG -# include -#else -# include "m4private.h" -#endif - -#include "execute.h" -#include "memchr2.h" -#include "memcmp2.h" -#include "quotearg.h" -#include "stdlib--.h" -#include "tempname.h" -#include "unistd--.h" - -#include - -extern void m4_set_sysval (int); -extern void m4_sysval_flush (m4 *, bool); -extern void m4_dump_symbols (m4 *, m4_dump_symbol_data *, size_t, - m4_macro_args *, bool); -extern const char *m4_expand_ranges (const char *, size_t *, m4_obstack *); -extern void m4_make_temp (m4 *, m4_obstack *, const m4_call_info *, - const char *, size_t, bool); - -/* Maintain each of the builtins implemented in this modules along - with their details in a single table for easy maintenance. - - function macros blind side minargs maxargs */ -#define builtin_functions \ - BUILTIN (changecom, false, false, false, 0, 2 ) \ - BUILTIN (changequote, false, false, false, 0, 2 ) \ - BUILTIN (decr, false, true, true, 1, 1 ) \ - BUILTIN (define, true, true, false, 1, 2 ) \ - BUILTIN (defn, true, true, false, 1, -1 ) \ - BUILTIN (divert, false, false, false, 0, 2 ) \ - BUILTIN (divnum, false, false, false, 0, 0 ) \ - BUILTIN (dnl, false, false, false, 0, 0 ) \ - BUILTIN (dumpdef, true, false, false, 0, -1 ) \ - BUILTIN (errprint, false, true, false, 1, -1 ) \ - BUILTIN (eval, false, true, true, 1, 3 ) \ - BUILTIN (ifdef, true, true, false, 2, 3 ) \ - BUILTIN (ifelse, true, true, false, 1, -1 ) \ - BUILTIN (include, false, true, false, 1, 1 ) \ - BUILTIN (incr, false, true, true, 1, 1 ) \ - BUILTIN (index, false, true, true, 2, 3 ) \ - BUILTIN (len, false, true, true, 1, 1 ) \ - BUILTIN (m4exit, false, false, false, 0, 1 ) \ - BUILTIN (m4wrap, true, true, false, 1, -1 ) \ - BUILTIN (maketemp, false, true, false, 1, 1 ) \ - BUILTIN (mkstemp, false, true, false, 1, 1 ) \ - BUILTIN (popdef, true, true, false, 1, -1 ) \ - BUILTIN (pushdef, true, true, false, 1, 2 ) \ - BUILTIN (shift, true, true, false, 1, -1 ) \ - BUILTIN (sinclude, false, true, false, 1, 1 ) \ - BUILTIN (substr, false, true, true, 2, 4 ) \ - BUILTIN (syscmd, false, true, true, 1, 1 ) \ - BUILTIN (sysval, false, false, false, 0, 0 ) \ - BUILTIN (traceoff, true, false, false, 0, -1 ) \ - BUILTIN (traceon, true, false, false, 0, -1 ) \ - BUILTIN (translit, false, true, true, 2, 3 ) \ - BUILTIN (undefine, true, true, false, 1, -1 ) \ - BUILTIN (undivert, false, false, false, 0, -1 ) \ - - -typedef intmax_t number; -typedef uintmax_t unumber; - -static void include (m4 *context, m4_obstack *obs, size_t argc, - m4_macro_args *argv, bool silent); -static int dumpdef_cmp_CB (const void *s1, const void *s2); -static void * dump_symbol_CB (m4_symbol_table *, const char *, size_t, - m4_symbol *symbol, void *userdata); -static const char *ntoa (number value, int radix); -static void numb_obstack (m4_obstack *obs, number value, - int radix, int min); - - -/* Generate prototypes for each builtin handler function. */ -#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN (handler) - builtin_functions -#undef BUILTIN - - -/* Generate a table for mapping m4 symbol names to handler functions. */ -static const m4_builtin m4_builtin_table[] = -{ -#define BUILTIN(handler, macros, blind, side, min, max) \ - M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max) - - builtin_functions -#undef BUILTIN - - { NULL, NULL, 0, 0, 0 }, -}; - - -void -include_m4 (m4 *context, m4_module *module, m4_obstack *obs) -{ - m4_install_builtins (context, module, m4_builtin_table); -} - - - -/* The rest of this file is code for builtins and expansion of user - defined macros. All the functions for builtins have a prototype as: - - void builtin_MACRONAME (m4_obstack *obs, int argc, char *argv[]); - - The function are expected to leave their expansion on the obstack OBS, - as an unfinished object. ARGV is a table of ARGC pointers to the - individual arguments to the macro. Please note that in general - argv[argc] != NULL. */ - -M4BUILTIN_HANDLER (define) -{ - const m4_call_info *me = m4_arg_info (argv); - - if (m4_is_arg_text (argv, 1)) - { - m4_symbol_value *value = m4_symbol_value_create (); - - if (m4_symbol_value_copy (context, value, m4_arg_symbol (argv, 2))) - m4_warn (context, 0, me, _("cannot concatenate builtins")); - m4_symbol_define (M4SYMTAB, M4ARG (1), M4ARGLEN (1), value); - } - else - m4_warn (context, 0, me, _("invalid macro name ignored")); -} - -M4BUILTIN_HANDLER (undefine) -{ - size_t i; - for (i = 1; i < argc; i++) - if (m4_symbol_value_lookup (context, argv, i, true)) - m4_symbol_delete (M4SYMTAB, M4ARG (i), M4ARGLEN (i)); -} - -M4BUILTIN_HANDLER (pushdef) -{ - const m4_call_info *me = m4_arg_info (argv); - - if (m4_is_arg_text (argv, 1)) - { - m4_symbol_value *value = m4_symbol_value_create (); - - if (m4_symbol_value_copy (context, value, m4_arg_symbol (argv, 2))) - m4_warn (context, 0, me, _("cannot concatenate builtins")); - m4_symbol_pushdef (M4SYMTAB, M4ARG (1), M4ARGLEN (1), value); - } - else - m4_warn (context, 0, me, _("invalid macro name ignored")); -} - -M4BUILTIN_HANDLER (popdef) -{ - size_t i; - for (i = 1; i < argc; i++) - if (m4_symbol_value_lookup (context, argv, i, true)) - m4_symbol_popdef (M4SYMTAB, M4ARG (i), M4ARGLEN (i)); -} - - - -/* --- CONDITIONALS OF M4 --- */ - - -M4BUILTIN_HANDLER (ifdef) -{ - m4_push_arg (context, obs, argv, - m4_symbol_value_lookup (context, argv, 1, false) ? 2 : 3); -} - -M4BUILTIN_HANDLER (ifelse) -{ - const m4_call_info *me = m4_arg_info (argv); - size_t i; - - /* The valid ranges of argc for ifelse is discontinuous, we cannot - rely on the regular mechanisms. */ - if (argc == 2 || m4_bad_argc (context, argc, me, 3, -1, false)) - return; - else if (argc % 3 == 0) - /* Diagnose excess arguments if 5, 8, 11, etc., actual arguments. */ - m4_bad_argc (context, argc, me, 0, argc - 2, false); - - i = 1; - argc--; - - while (true) - { - if (m4_arg_equal (context, argv, i, i + 1)) - { - m4_push_arg (context, obs, argv, i + 2); - return; - } - switch (argc) - { - case 3: - return; - - case 4: - case 5: - m4_push_arg (context, obs, argv, i + 3); - return; - - default: - argc -= 3; - i += 3; - } - } -} - - -/* qsort comparison routine, for sorting the table made in m4_dumpdef (). */ -static int -dumpdef_cmp_CB (const void *s1, const void *s2) -{ - const m4_string *a = (const m4_string *) s1; - const m4_string *b = (const m4_string *) s2; - return memcmp2 (a->str, a->len, b->str, b->len); -} - -/* The function m4_dump_symbols () is for use by "dumpdef". It builds up a - table of all defined symbol names. */ -static void * -dump_symbol_CB (m4_symbol_table *ignored M4_GNUC_UNUSED, const char *name, - size_t len, m4_symbol *symbol, void *userdata) -{ - m4_dump_symbol_data *symbol_data = (m4_dump_symbol_data *) userdata; - m4_string *key; - - assert (name); - assert (symbol); - assert (!m4_is_symbol_value_void (m4_get_symbol_value (symbol))); - - if (symbol_data->size == 0) - { - char *base; - size_t offset = obstack_object_size (symbol_data->obs); - obstack_blank (symbol_data->obs, sizeof *symbol_data->base); - symbol_data->size = (obstack_room (symbol_data->obs) - / sizeof *symbol_data->base); - base = (char *) obstack_base (symbol_data->obs) + offset; - symbol_data->base = (m4_string *) base; - } - else - { - obstack_blank_fast (symbol_data->obs, sizeof *symbol_data->base); - symbol_data->size--; - } - - /* Safe to cast away const, since m4_dump_symbols adds it back. */ - key = (m4_string *) symbol_data->base++; - key->str = (char *) name; - key->len = len; - return NULL; -} - -/* If there are no arguments, build a sorted list of all defined - symbols, otherwise, only the specified symbols. */ -void -m4_dump_symbols (m4 *context, m4_dump_symbol_data *data, size_t argc, - m4_macro_args *argv, bool complain) -{ - assert (obstack_object_size (data->obs) == 0); - data->size = obstack_room (data->obs) / sizeof *data->base; - data->base = (m4_string *) obstack_base (data->obs); - - if (argc == 1) - m4_symtab_apply (M4SYMTAB, false, dump_symbol_CB, data); - else - { - size_t i; - m4_symbol *symbol; - - for (i = 1; i < argc; i++) - { - symbol = m4_symbol_value_lookup (context, argv, i, complain); - if (symbol) - dump_symbol_CB (NULL, M4ARG (i), M4ARGLEN (i), symbol, data); - } - } - - data->size = obstack_object_size (data->obs) / sizeof *data->base; - data->base = (m4_string *) obstack_finish (data->obs); - /* Safe to cast away const, since we don't modify entries. */ - qsort ((m4_string *) data->base, data->size, sizeof *data->base, - dumpdef_cmp_CB); -} - - -/* Implementation of "dumpdef" itself. It builds up a table of pointers to - symbols, sorts it and prints the sorted table. */ -M4BUILTIN_HANDLER (dumpdef) -{ - m4_dump_symbol_data data; - const m4_string_pair *quotes = NULL; - bool stack = m4_is_debug_bit (context, M4_DEBUG_TRACE_STACK); - size_t arg_length = m4_get_max_debug_arg_length_opt (context); - bool module = m4_is_debug_bit (context, M4_DEBUG_TRACE_MODULE); - FILE *output = (m4_is_debug_bit (context, M4_DEBUG_TRACE_OUTPUT_DUMPDEF) - ? stderr : m4_get_debug_file (context)); - - if (!output) - return; - if (m4_is_debug_bit (context, M4_DEBUG_TRACE_QUOTE)) - quotes = m4_get_syntax_quotes (M4SYNTAX); - data.obs = m4_arg_scratch (context); - m4_dump_symbols (context, &data, argc, argv, true); - m4_sysval_flush (context, false); - - for (; data.size > 0; --data.size, data.base++) - { - m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, data.base->str, - data.base->len); - char *value; - size_t len; - assert (symbol); - - /* TODO - add debugmode(b) option to control quoting style. */ - obstack_grow (obs, data.base->str, data.base->len); - obstack_1grow (obs, ':'); - obstack_1grow (obs, '\t'); - m4_symbol_print (context, symbol, obs, quotes, stack, arg_length, - module); - obstack_1grow (obs, '\n'); - len = obstack_object_size (obs); - value = (char *) obstack_finish (obs); - fwrite (value, 1, len, output); - obstack_free (obs, value); - } -} - -/* The macro "defn" returns the quoted definition of the macro named by - the first argument. If the macro is builtin, it will push a special - macro-definition token on the input stack. */ -M4BUILTIN_HANDLER (defn) -{ - const m4_call_info *me = m4_arg_info (argv); - size_t i; - - for (i = 1; i < argc; i++) - { - m4_symbol *symbol = m4_symbol_value_lookup (context, argv, i, true); - - if (!symbol) - ; - else if (m4_is_symbol_text (symbol)) - m4_shipout_string (context, obs, m4_get_symbol_text (symbol), - m4_get_symbol_len (symbol), true); - else if (m4_is_symbol_func (symbol)) - m4_push_builtin (context, obs, m4_get_symbol_value (symbol)); - else if (m4_is_symbol_placeholder (symbol)) - m4_warn (context, 0, me, - _("%s: builtin %s requested by frozen file not found"), - quotearg_n_mem (2, M4ARG (i), M4ARGLEN (i)), - quotearg_style (locale_quoting_style, - m4_get_symbol_placeholder (symbol))); - else - { - assert (!"Bad token data type in m4_defn"); - abort (); - } - } -} - - -/* This section contains macros to handle the builtins "syscmd" - and "sysval". */ - -/* Exit code from last "syscmd" command. */ -/* FIXME - we should preserve this value across freezing. See - http://lists.gnu.org/archive/html/bug-m4/2006-06/msg00059.html - for ideas on how do to that. */ -static int m4_sysval = 0; - -void -m4_set_sysval (int value) -{ - m4_sysval = value; -} - -/* Flush a given output STREAM. If REPORT, also print an error - message and clear the stream error bit. */ -static void -sysval_flush_helper (m4 *context, FILE *stream, bool report) -{ - if (fflush (stream) == EOF && report) - { - m4_error (context, 0, errno, NULL, _("write error")); - clearerr (stream); - } -} - -/* Flush all user output streams, prior to doing something that can - could lose unflushed data or interleave debug and normal output - incorrectly. If REPORT, then print an error message on failure and - clear the stream error bit; otherwise a subsequent ferror can track - that an error occurred. */ -void -m4_sysval_flush (m4 *context, bool report) -{ - FILE *debug_file = m4_get_debug_file (context); - - if (debug_file != stdout) - sysval_flush_helper (context, stdout, report); - if (debug_file != stderr) - /* If we have problems with stderr, we can't really report that - problem to stderr. The closeout module will ensure the exit - status reflects the problem, though. */ - fflush (stderr); - if (debug_file != NULL) - sysval_flush_helper (context, debug_file, report); - /* POSIX requires that if m4 doesn't consume all input, but stdin is - opened on a seekable file, that the file pointer be left at the - next character on exit (but places no restrictions on the file - pointer location on a non-seekable file). It also requires that - fflush() followed by fseeko() on an input file set the underlying - file pointer, and gnulib guarantees these semantics. However, - fflush() on a non-seekable file can lose buffered data, which we - might otherwise want to process after syscmd. Hence, we must - check whether stdin is seekable. We must also be tolerant of - operating with stdin closed, so we don't report any failures in - this attempt. The stdio-safer module and friends are essential, - so that if stdin was closed, this lseek is not on some other file - that we have since opened. */ - if (lseek (STDIN_FILENO, 0, SEEK_CUR) >= 0 - && fflush (stdin) == 0) - { - fseeko (stdin, 0, SEEK_CUR); - } -} - -M4BUILTIN_HANDLER (syscmd) -{ - const m4_call_info *me = m4_arg_info (argv); - const char *cmd = M4ARG (1); - size_t len = M4ARGLEN (1); - int status; - int sig_status; - const char *prog_args[4] = { "sh", "-c" }; - - if (m4_get_safer_opt (context)) - { - m4_error (context, 0, 0, m4_arg_info (argv), _("disabled by --safer")); - return; - } - if (strlen (cmd) != len) - m4_warn (context, 0, me, _("argument %s truncated"), - quotearg_style_mem (locale_quoting_style, cmd, len)); - - /* Optimize the empty command. */ - if (!*cmd) - { - m4_set_sysval (0); - return; - } - m4_sysval_flush (context, false); -#if W32_NATIVE - if (strstr (M4_SYSCMD_SHELL, "cmd")) - { - prog_args[0] = "cmd"; - prog_args[1] = "/c"; - } -#endif - prog_args[2] = cmd; - errno = 0; - status = execute (m4_info_name (me), M4_SYSCMD_SHELL, (char **) prog_args, - false, false, false, false, true, false, &sig_status); - if (sig_status) - { - assert (status == 127); - m4_sysval = sig_status << 8; - } - else - { - if (status == 127 && errno) - m4_warn (context, errno, me, _("cannot run command %s"), - quotearg_style (locale_quoting_style, cmd)); - m4_sysval = status; - } -} - - -M4BUILTIN_HANDLER (sysval) -{ - m4_shipout_int (obs, m4_sysval); -} - - -M4BUILTIN_HANDLER (incr) -{ - int value; - - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), - &value)) - return; - - m4_shipout_int (obs, value + 1); -} - -M4BUILTIN_HANDLER (decr) -{ - int value; - - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), - &value)) - return; - - m4_shipout_int (obs, value - 1); -} - - -/* This section contains the macros "divert", "undivert" and "divnum" for - handling diversion. The utility functions used lives in output.c. */ - -/* Divert further output to the diversion given by ARGV[1]. Out of range - means discard further output. */ -M4BUILTIN_HANDLER (divert) -{ - int i = 0; - - if (argc >= 2 && !m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), - M4ARGLEN (1), &i)) - return; - m4_make_diversion (context, i); - m4_divert_text (context, NULL, M4ARG (2), M4ARGLEN (2), - m4_get_current_line (context)); -} - -/* Expand to the current diversion number. */ -M4BUILTIN_HANDLER (divnum) -{ - m4_shipout_int (obs, m4_get_current_diversion (context)); -} - -/* Bring back the diversion given by the argument list. If none is - specified, bring back all diversions. GNU specific is the option - of undiverting the named file, by passing a non-numeric argument to - undivert (). */ - -M4BUILTIN_HANDLER (undivert) -{ - size_t i = 0; - const m4_call_info *me = m4_arg_info (argv); - - if (argc == 1) - m4_undivert_all (context); - else - for (i = 1; i < argc; i++) - { - const char *str = M4ARG (i); - size_t len = M4ARGLEN (i); - char *endp; - int diversion = strtol (str, &endp, 10); - if (endp - str == len && !isspace ((unsigned char) *str)) - m4_insert_diversion (context, diversion); - else if (m4_get_posixly_correct_opt (context)) - m4_warn (context, 0, me, _("non-numeric argument %s"), - quotearg_style_mem (locale_quoting_style, str, len)); - else if (strlen (str) != len) - m4_warn (context, 0, me, _("invalid file name %s"), - quotearg_style_mem (locale_quoting_style, str, len)); - else - { - char *filepath = m4_path_search (context, str, NULL); - FILE *fp = m4_fopen (context, filepath, "r"); - - free (filepath); - if (fp != NULL) - { - m4_insert_file (context, fp); - if (fclose (fp) == EOF) - m4_error (context, 0, errno, me, _("error undiverting %s"), - quotearg_style (locale_quoting_style, str)); - } - else - m4_error (context, 0, errno, me, _("cannot undivert %s"), - quotearg_style (locale_quoting_style, str)); - } - } -} - - -/* This section contains various macros, which does not fall into - any specific group. These are "dnl", "shift", "changequote", - "changecom" and "changesyntax" */ - -/* Delete all subsequent whitespace from input. The function skip_line () - lives in input.c. */ -M4BUILTIN_HANDLER (dnl) -{ - m4_skip_line (context, m4_arg_info (argv)); -} - -/* Shift all arguments one to the left, discarding the first argument. - Each output argument is quoted with the current quotes. */ -M4BUILTIN_HANDLER (shift) -{ - m4_push_args (context, obs, argv, true, true); -} - -/* Change the current quotes. The function set_quotes () lives in - syntax.c. */ -M4BUILTIN_HANDLER (changequote) -{ - m4_set_quotes (M4SYNTAX, - (argc >= 2) ? M4ARG (1) : NULL, M4ARGLEN (1), - (argc >= 3) ? M4ARG (2) : NULL, M4ARGLEN (2)); -} - -/* Change the current comment delimiters. The function set_comment () - lives in syntax.c. */ -M4BUILTIN_HANDLER (changecom) -{ - m4_set_comment (M4SYNTAX, - (argc >= 2) ? M4ARG (1) : NULL, M4ARGLEN (1), - (argc >= 3) ? M4ARG (2) : NULL, M4ARGLEN (2)); -} - - -/* This section contains macros for inclusion of other files -- "include" - and "sinclude". This differs from bringing back diversions, in that - the input is scanned before being copied to the output. */ - -static void -include (m4 *context, m4_obstack *obs, size_t argc, m4_macro_args *argv, bool silent) -{ - const m4_call_info *me = m4_arg_info (argv); - const char *arg = M4ARG (1); - size_t len = M4ARGLEN (1); - - if (strlen (arg) != len) - m4_warn (context, 0, me, _("argument %s truncated"), - quotearg_style_mem (locale_quoting_style, arg, len)); - m4_load_filename (context, me, arg, obs, silent); -} - -/* Include a file, complaining in case of errors. */ -M4BUILTIN_HANDLER (include) -{ - include (context, obs, argc, argv, false); -} - -/* Include a file, ignoring errors. */ -M4BUILTIN_HANDLER (sinclude) -{ - include (context, obs, argc, argv, true); -} - - -/* More miscellaneous builtins -- "maketemp", "errprint". */ - -/* Add trailing `X' to PATTERN of length LEN as necessary, then - securely create the temporary file system object. If DIR, create a - directory instead of a file. Report errors on behalf of CALLER. If - successful, output the quoted resulting name on OBS. */ -void -m4_make_temp (m4 *context, m4_obstack *obs, const m4_call_info *caller, - const char *pattern, size_t len, bool dir) -{ - int fd; - int i; - char *name; - const m4_string_pair *quotes = m4_get_syntax_quotes (M4SYNTAX); - - if (m4_get_safer_opt (context)) - { - m4_error (context, 0, 0, caller, _("disabled by --safer")); - return; - } - - /* Guarantee that there are six trailing 'X' characters, even if the - user forgot to supply them. Output must be quoted if - successful. */ - assert (obstack_object_size (obs) == 0); - obstack_grow (obs, quotes->str1, quotes->len1); - if (strlen (pattern) < len) - { - m4_warn (context, 0, caller, _("argument %s truncated"), - quotearg_style_mem (locale_quoting_style, pattern, len)); - len = strlen (pattern); - } - obstack_grow (obs, pattern, len); - for (i = 0; len > 0 && i < 6; i++) - if (pattern[--len] != 'X') - break; - obstack_grow0 (obs, "XXXXXX", 6 - i); - name = (char *) obstack_base (obs) + quotes->len1; - - /* Make the temporary object. */ - errno = 0; - fd = gen_tempname (name, 0, 0, dir ? GT_DIR : GT_FILE); - if (fd < 0) - { - /* This use of _() will need to change if xgettext ever changes - its undocumented behavior of parsing both string options. */ - - m4_warn (context, errno, caller, - _(dir ? "cannot create directory from template %s" - : "cannot create file from template %s"), - quotearg_style (locale_quoting_style, pattern)); - obstack_free (obs, obstack_finish (obs)); - } - else - { - if (!dir) - close (fd); - /* Remove NUL, then finish quote. */ - obstack_blank_fast (obs, -1); - obstack_grow (obs, quotes->str2, quotes->len2); - } -} - -/* Use the first argument as at template for a temporary file name. */ -M4BUILTIN_HANDLER (maketemp) -{ - const m4_call_info *me = m4_arg_info (argv); - m4_warn (context, 0, me, _("recommend using mkstemp instead")); - if (m4_get_posixly_correct_opt (context)) - { - /* POSIX states "any trailing 'X' characters [are] replaced with - the current process ID as a string", without referencing the - file system. Horribly insecure, but we have to do it. - - For reference, Solaris m4 does: - maketemp() -> `' - maketemp(X) -> `X' - maketemp(XX) -> `Xn', where n is last digit of pid - maketemp(XXXXXXXX) -> `X00nnnnn', where nnnnn is 16-bit pid - */ - const char *str = M4ARG (1); - size_t len = M4ARGLEN (1); - size_t i; - m4_obstack *scratch = m4_arg_scratch (context); - size_t pid_len = obstack_printf (scratch, "%lu", - (unsigned long) getpid ()); - char *pid = (char *) obstack_copy0 (scratch, "", 0); - - for (i = len; i > 1; i--) - if (str[i - 1] != 'X') - break; - obstack_grow (obs, str, i); - if (len - i < pid_len) - obstack_grow (obs, pid + pid_len - (len - i), len - i); - else - obstack_printf (obs, "%.*d%s", (int) (len - i - pid_len), 0, pid); - } - else - m4_make_temp (context, obs, me, M4ARG (1), M4ARGLEN (1), false); -} - -/* Use the first argument as a template for a temporary file name. */ -M4BUILTIN_HANDLER (mkstemp) -{ - m4_make_temp (context, obs, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), - false); -} - -/* Print all arguments on standard error. */ -M4BUILTIN_HANDLER (errprint) -{ - size_t i; - - m4_sysval_flush (context, false); - /* The close_stdin module makes it safe to skip checking the return - values here. */ - fwrite (M4ARG (1), 1, M4ARGLEN (1), stderr); - for (i = 2; i < m4_arg_argc (argv); i++) - { - fputc (' ', stderr); - fwrite (M4ARG (i), 1, M4ARGLEN (i), stderr); - } - fflush (stderr); -} - - -/* This section contains various macros for exiting, saving input until - EOF is seen, and tracing macro calls. That is: "m4exit", "m4wrap", - "traceon" and "traceoff". */ - -/* Exit immediately, with exitcode specified by the first argument, 0 if no - arguments are present. */ -M4BUILTIN_HANDLER (m4exit) -{ - const m4_call_info *me = m4_arg_info (argv); - int exit_code = EXIT_SUCCESS; - - /* Warn on bad arguments, but still exit. */ - if (argc >= 2 && !m4_numeric_arg (context, me, M4ARG (1), M4ARGLEN (1), - &exit_code)) - exit_code = EXIT_FAILURE; - if (exit_code < 0 || exit_code > 255) - { - m4_warn (context, 0, me, _("exit status out of range: `%d'"), exit_code); - exit_code = EXIT_FAILURE; - } - - /* Ensure that atexit handlers see correct nonzero status. */ - if (exit_code != EXIT_SUCCESS) - m4_set_exit_failure (exit_code); - - /* Change debug stream back to stderr, to force flushing debug - stream and detect any errors. */ - m4_debug_set_output (context, me, NULL); - m4_sysval_flush (context, true); - - /* Check for saved error. */ - if (exit_code == 0 && m4_get_exit_status (context) != 0) - exit_code = m4_get_exit_status (context); - exit (exit_code); -} - -/* Save the argument text until EOF has been seen, allowing for user - specified cleanup action. GNU version saves all arguments, the standard - version only the first. */ -M4BUILTIN_HANDLER (m4wrap) -{ - m4_wrap_args (context, argv); -} - -/* Enable tracing of all specified macros, or all, if none is specified. - Tracing is disabled by default, when a macro is defined. This can be - overridden by the "t" debug flag. */ - -M4BUILTIN_HANDLER (traceon) -{ - const m4_call_info *me = m4_arg_info (argv); - size_t i; - - if (argc == 1) - m4_set_debug_level_opt (context, (m4_get_debug_level_opt (context) - | M4_DEBUG_TRACE_ALL)); - else - for (i = 1; i < argc; i++) - if (m4_is_arg_text (argv, i)) - m4_set_symbol_name_traced (M4SYMTAB, M4ARG (i), M4ARGLEN (i), true); - else - m4_warn (context, 0, me, _("invalid macro name ignored")); -} - -/* Disable tracing of all specified macros, or all, if none is specified. */ -M4BUILTIN_HANDLER (traceoff) -{ - const m4_call_info *me = m4_arg_info (argv); - size_t i; - - if (argc == 1) - m4_set_debug_level_opt (context, (m4_get_debug_level_opt (context) - & ~M4_DEBUG_TRACE_ALL)); - else - for (i = 1; i < argc; i++) - if (m4_is_arg_text (argv, i)) - m4_set_symbol_name_traced (M4SYMTAB, M4ARG (i), M4ARGLEN (i), false); - else - m4_warn (context, 0, me, _("invalid macro name ignored")); -} - - -/* This section contains text processing macros: "len", "index", - "substr", "translit", "format", "regexp" and "patsubst". The last - three are GNU specific. */ - -/* Expand to the length of the first argument. */ -M4BUILTIN_HANDLER (len) -{ - m4_shipout_int (obs, M4ARGLEN (1)); -} - -/* The macro expands to the first index of the second argument in the - first argument. As an extension, start the search at the index - indicated by the third argument. */ -M4BUILTIN_HANDLER (index) -{ - const char *haystack = M4ARG (1); - size_t haystack_len = M4ARGLEN (1); - const char *needle = M4ARG (2); - const char *result = NULL; - int offset = 0; - int retval = -1; - - if (!m4_arg_empty (argv, 3) && !m4_numeric_arg (context, m4_arg_info (argv), - M4ARG (3), M4ARGLEN (3), - &offset)) - return; - if (offset < 0) - { - offset += haystack_len; - if (offset < 0) - offset = 0; - } - else if (haystack_len < offset) - { - m4_shipout_int (obs, -1); - return; - } - - /* Rely on the optimizations guaranteed by gnulib's memmem - module. */ - result = (char *) memmem (haystack + offset, haystack_len - offset, needle, - M4ARGLEN (2)); - if (result) - retval = result - haystack; - - m4_shipout_int (obs, retval); -} - -/* The macro "substr" extracts substrings from the first argument, - starting from the index given by the second argument, extending for - a length given by the third argument. If the third argument is - missing or empty, the substring extends to the end of the first - argument. As an extension, negative arguments are treated as - indices relative to the string length. Also, if a fourth argument - is supplied, the original string is output with the selected - substring replaced by the argument. */ -M4BUILTIN_HANDLER (substr) -{ - const m4_call_info *me = m4_arg_info (argv); - const char *str = M4ARG (1); - int start = 0; - int end; - int length; - - if (argc <= 2) - { - m4_push_arg (context, obs, argv, 1); - return; - } - - length = M4ARGLEN (1); - if (!m4_arg_empty (argv, 2) - && !m4_numeric_arg (context, me, M4ARG (2), M4ARGLEN (2), &start)) - return; - if (start < 0) - start += length; - - if (m4_arg_empty (argv, 3)) - end = length; - else - { - if (!m4_numeric_arg (context, me, M4ARG (3), M4ARGLEN (3), &end)) - return; - if (end < 0) - end += length; - else - end += start; - } - - if (5 <= argc) - { - /* Replacement text provided. */ - if (end < start) - end = start; - if (end < 0 || length < start) - { - m4_warn (context, 0, me, _("substring out of range")); - return; - } - if (start < 0) - start = 0; - if (length < end) - end = length; - obstack_grow (obs, str, start); - m4_push_arg (context, obs, argv, 4); - obstack_grow (obs, str + end, length - end); - return; - } - - if (start < 0) - start = 0; - if (length < end) - end = length; - if (end <= start) - return; - - obstack_grow (obs, str + start, end - start); -} - - -/* Any ranges in string S of length *LEN are expanded, using OBS for - scratch space, and the expansion returned. *LEN is set to the - expanded length. A single - (dash) can be included in the strings - by being the first or the last character in the string. If the - first character in a range is after the first in the character set, - the range is made backwards, thus 9-0 is the string 9876543210. */ -const char * -m4_expand_ranges (const char *s, size_t *len, m4_obstack *obs) -{ - unsigned char from; - unsigned char to; - const char *end = s + *len; - - assert (obstack_object_size (obs) == 0); - assert (s != end); - from = *s++; - obstack_1grow (obs, from); - - for ( ; s != end; from = *s++) - { - if (*s == '-') - { - if (++s == end) - { - /* trailing dash */ - obstack_1grow (obs, '-'); - break; - } - to = *s; - if (from <= to) - { - while (from++ < to) - obstack_1grow (obs, from); - } - else - { - while (--from >= to) - obstack_1grow (obs, from); - } - } - else - obstack_1grow (obs, *s); - } - *len = obstack_object_size (obs); - return (char *) obstack_finish (obs); -} - -/* The macro "translit" translates all characters in the first - argument, which are present in the second argument, into the - corresponding character from the third argument. If the third - argument is shorter than the second, the extra characters in the - second argument are deleted from the first. */ -M4BUILTIN_HANDLER (translit) -{ - const char *data; - const char *from; - const char *to; - size_t from_len; - size_t to_len; - char map[UCHAR_MAX + 1]; - char found[UCHAR_MAX + 1]; - unsigned char ch; - - enum { ASIS, REPLACE, DELETE }; - - if (m4_arg_empty (argv, 1) || m4_arg_empty (argv, 2)) - { - m4_push_arg (context, obs, argv, 1); - return; - } - - from = M4ARG (2); - from_len = M4ARGLEN (2); - - to = M4ARG (3); - to_len = M4ARGLEN (3); - if (memchr (to, '-', to_len) != NULL) - to = m4_expand_ranges (to, &to_len, m4_arg_scratch (context)); - - /* If there are only one or two bytes to replace, it is faster to - use memchr2. Using expand_ranges does nothing unless there are - at least three bytes. */ - if (from_len <= 2) - { - const char *p; - size_t len = M4ARGLEN (1); - int second = from[from_len / 2]; - data = M4ARG (1); - while ((p = (char *) memchr2 (data, from[0], second, len))) - { - obstack_grow (obs, data, p - data); - len -= p - data + 1; - data = p + 1; - if (*p == from[0] && to_len) - obstack_1grow (obs, to[0]); - else if (*p == second && 1 < to_len) - obstack_1grow (obs, to[1]); - } - obstack_grow (obs, data, len); - return; - } - - if (memchr (from, '-', from_len) != NULL) - from = m4_expand_ranges (from, &from_len, m4_arg_scratch (context)); - - /* Calling memchr(from) for each character in data is quadratic, - since both strings can be arbitrarily long. Instead, create a - from-to mapping in one pass of from, then use that map in one - pass of data, for linear behavior. Traditional behavior is that - only the first instance of a character in from is consulted, - hence the found map. */ - memset (map, 0, sizeof map); - memset (found, 0, sizeof found); - while (from_len--) - { - ch = *from++; - if (found[ch] == ASIS) - { - if (to_len) - { - found[ch] = REPLACE; - map[ch] = *to; - } - else - found[ch] = DELETE; - } - if (to_len) - { - to++; - to_len--; - } - } - - data = M4ARG (1); - from_len = M4ARGLEN (1); - while (from_len--) - { - ch = *data++; - switch (found[ch]) - { - case ASIS: - obstack_1grow (obs, ch); - break; - case REPLACE: - obstack_1grow (obs, map[ch]); - break; - case DELETE: - break; - default: - assert (!"translit"); - abort (); - } - } -} - - - -/* The rest of this file contains the functions to evaluate integer - * expressions for the "eval" macro. `number' should be at least 32 bits. - */ -#define numb_set(ans, x) ((ans) = (x)) -#define numb_set_si(ans, si) (*(ans) = (number) (si)) - -#define numb_ZERO ((number) 0) -#define numb_ONE ((number) 1) - -#define numb_init(x) ((x) = numb_ZERO) -#define numb_fini(x) - -#define numb_incr(n) ((n) += numb_ONE) -#define numb_decr(n) ((n) -= numb_ONE) - -#define numb_zerop(x) ((x) == numb_ZERO) -#define numb_positivep(x) ((x) > numb_ZERO) -#define numb_negativep(x) ((x) < numb_ZERO) - -#define numb_eq(x, y) ((x) = ((x) == (y))) -#define numb_ne(x, y) ((x) = ((x) != (y))) -#define numb_lt(x, y) ((x) = ((x) < (y))) -#define numb_le(x, y) ((x) = ((x) <= (y))) -#define numb_gt(x, y) ((x) = ((x) > (y))) -#define numb_ge(x, y) ((x) = ((x) >= (y))) - -#define numb_lnot(x) ((x) = (!(x))) -#define numb_lior(x, y) ((x) = ((x) || (y))) -#define numb_land(x, y) ((x) = ((x) && (y))) - -#define numb_not(c, x) (*(x) = ~ *(x)) -#define numb_eor(c, x, y) (*(x) = *(x) ^ *(y)) -#define numb_ior(c, x, y) (*(x) = *(x) | *(y)) -#define numb_and(c, x, y) (*(x) = *(x) & *(y)) - -#define numb_plus(x, y) ((x) = ((x) + (y))) -#define numb_minus(x, y) ((x) = ((x) - (y))) -#define numb_negate(x) ((x) = (- (x))) - -#define numb_times(x, y) ((x) = ((x) * (y))) -/* Be careful of x86 SIGFPE. */ -#define numb_ratio(x, y) \ - (((y) == -1) ? (numb_negate (x)) : ((x) /= (y))) -#define numb_divide(x, y) \ - ((*(y) == -1) ? (numb_negate (*(y))) : (*(x) /= *(y))) -#define numb_modulo(c, x, y) \ - ((*(y) == -1) ? (*(x) = numb_ZERO) : (*(x) %= *(y))) -/* numb_invert is only used in the context of x**-y, which integral math - does not support. */ -#define numb_invert(x) return NEGATIVE_EXPONENT - -/* Minimize undefined C behavior (shifting by a negative number, - shifting by the width or greater, left shift overflow, or right - shift of a negative number). Implement Java wrap-around semantics, - with implicit masking of shift amount. This code assumes that the - implementation-defined overflow when casting unsigned to signed is - a silent twos-complement wrap-around. */ -#define shift_mask (sizeof (number) * CHAR_BIT - 1) -#define numb_lshift(c, x, y) \ - (*(x) = (number) ((unumber) *(x) << (*(y) & shift_mask))) -#define numb_rshift(c, x, y) \ - (*(x) = (number) (*(x) < 0 \ - ? ~(~(unumber) *(x) >> (*(y) & shift_mask)) \ - : (unumber) *(x) >> (*(y) & shift_mask))) -#define numb_urshift(c, x, y) \ - (*(x) = (number) ((unumber) *(x) >> (*(y) & shift_mask))) - - -/* The function ntoa () converts VALUE to a signed ASCII representation in - radix RADIX. Radix must be between 2 and 36, inclusive. */ -static const char * -ntoa (number value, int radix) -{ - /* Digits for number to ASCII conversions. */ - static char const ntoa_digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - - bool negative; - unumber uvalue; - /* Sized for radix 2, plus sign and trailing NUL. */ - static char str[sizeof value * CHAR_BIT + 2]; - char *s = &str[sizeof str]; - - *--s = '\0'; - - if (value < 0) - { - negative = true; - uvalue = (unumber) -value; - } - else - { - negative = false; - uvalue = (unumber) value; - } - - do - { - *--s = ntoa_digits[uvalue % radix]; - uvalue /= radix; - } - while (uvalue > 0); - - if (negative) - *--s = '-'; - return s; -} - -static void -numb_obstack (m4_obstack *obs, number value, int radix, int min) -{ - const char *s; - size_t len; - unumber uvalue; - - if (radix == 1) - { - if (value < 0) - { - obstack_1grow (obs, '-'); - uvalue = -value; - } - else - uvalue = value; - if (uvalue < min) - { - obstack_blank (obs, min - uvalue); - memset ((char *) obstack_next_free (obs) - (min - uvalue), '0', - min - uvalue); - } - obstack_blank (obs, uvalue); - memset ((char *) obstack_next_free (obs) - uvalue, '1', uvalue); - return; - } - - s = ntoa (value, radix); - - if (*s == '-') - { - obstack_1grow (obs, '-'); - s++; - } - len = strlen (s); - if (len < min) - { - min -= len; - obstack_blank (obs, min); - memset ((char *) obstack_next_free (obs) - min, '0', min); - } - obstack_grow (obs, s, len); -} - - -static void -numb_initialise (void) -{ - ; -} - -/* This macro defines the top level code for the "eval" builtin. The - actual work is done in the function m4_evaluate (), which lives in - evalparse.c. */ -#define m4_evaluate builtin_eval -#include "evalparse.c" diff --git a/modules/m4.h b/modules/m4.h deleted file mode 100644 index 769665e5..00000000 --- a/modules/m4.h +++ /dev/null @@ -1,53 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 2003, 2006-2008, 2010, 2013-2014, 2017 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 . -*/ - -#ifndef MODULES_M4_H -#define MODULES_M4_H 1 - -#include - -BEGIN_C_DECLS - -/* This structure is used to pass the information needed - from call to call in m4_dump_symbols. */ -typedef struct -{ - m4_obstack *obs; /* obstack for table */ - const m4_string *base; /* base of table */ - int size; /* size of table */ -} m4_dump_symbol_data; - - -/* Types used to cast imported symbols to, so we get type checking - across the interface boundary. */ -typedef void m4_sysval_flush_func (m4 *context, bool report); -typedef void m4_set_sysval_func (int value); -typedef void m4_dump_symbols_func (m4 *context, m4_dump_symbol_data *data, - size_t argc, m4_macro_args *argv, - bool complain); -typedef const char *m4_expand_ranges_func (const char *s, size_t *len, - m4_obstack *obs); -typedef void m4_make_temp_func (m4 *context, m4_obstack *obs, - const m4_call_info *macro, const char *name, - size_t len, bool dir); - -END_C_DECLS - -#endif /* !MODULES_M4_H */ diff --git a/modules/mpeval.c b/modules/mpeval.c deleted file mode 100644 index 1c998b6a..00000000 --- a/modules/mpeval.c +++ /dev/null @@ -1,453 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 2000-2001, 2006-2008, 2010, 2013-2014, 2017 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 . -*/ - -#include - -/* Build using only the exported interfaces, unless NDEBUG is set, in - which case use private symbols to speed things up as much as possible. */ -#ifndef NDEBUG -# include -#else -# include "m4private.h" -#endif - -#if HAVE_GMP_H -# include -#endif - -/* Maintain each of the builtins implemented in this modules along - with their details in a single table for easy maintenance. - - function macros blind side minargs maxargs */ -#define builtin_functions \ - BUILTIN (mpeval, false, true, true, 1, 3 ) \ - - - -#define numb_set(ans, i) mpq_set (ans, i) -#define numb_set_si(ans, i) mpq_set_si (*(ans), (long) i, (unsigned long) 1) - -#define numb_init(x) mpq_init (x) -#define numb_fini(x) mpq_clear (x) - -#define numb_zerop(x) (mpq_cmp (x, numb_ZERO) == 0) -#define numb_positivep(x) (mpq_cmp (x, numb_ZERO) > 0) -#define numb_negativep(x) (mpq_cmp (x, numb_ZERO) < 0) - -#define numb_eq(x, y) numb_set (x, mpq_cmp (x, y) == 0 ? numb_ONE : numb_ZERO) -#define numb_ne(x, y) numb_set (x, mpq_cmp (x, y) != 0 ? numb_ONE : numb_ZERO) -#define numb_lt(x, y) numb_set (x, mpq_cmp (x, y) < 0 ? numb_ONE : numb_ZERO) -#define numb_le(x, y) numb_set (x, mpq_cmp (x, y) <= 0 ? numb_ONE : numb_ZERO) -#define numb_gt(x, y) numb_set (x, mpq_cmp (x, y) > 0 ? numb_ONE : numb_ZERO) -#define numb_ge(x, y) numb_set (x, mpq_cmp (x, y) >= 0 ? numb_ONE : numb_ZERO) - -#define numb_lnot(x) numb_set (x, numb_zerop (x) ? numb_ONE : numb_ZERO) -#define numb_lior(x, y) numb_set (x, numb_zerop (x) ? y : x) -#define numb_land(x, y) numb_set (x, numb_zerop (x) ? numb_ZERO : y) - -#define reduce1(f1, x) \ - do \ - { \ - number T; \ - mpq_init (T); \ - f1 (T, x); \ - mpq_set (x, T); \ - mpq_clear (T); \ - } \ - while (0) -#define reduce2(f2,x,y) \ - do \ - { \ - number T; \ - mpq_init (T); \ - f2 (T, (x), (y)); \ - mpq_set ((x), T); \ - mpq_clear (T); \ - } \ - while (0) - -#define numb_plus(x, y) reduce2 (mpq_add, x, y) -#define numb_minus(x, y) reduce2 (mpq_sub, x, y) -#define numb_negate(x) reduce1 (mpq_neg, x) - -#define numb_times(x, y) reduce2 (mpq_mul, x, y) -#define numb_ratio(x, y) reduce2 (mpq_div, x, y) -#define numb_invert(x) reduce1 (mpq_inv, x) - -#define numb_incr(n) numb_plus (n, numb_ONE) -#define numb_decr(n) numb_minus (n, numb_ONE) - -/* Generate prototypes for each builtin handler function. */ -#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN (handler) - builtin_functions -#undef BUILTIN - - -/* Generate a table for mapping m4 symbol names to handler functions. */ -static const m4_builtin m4_builtin_table[] = -{ -#define BUILTIN(handler, macros, blind, side, min, max) \ - M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max) - - builtin_functions -#undef BUILTIN - - { NULL, NULL, 0, 0, 0 }, -}; - - -/* A table for mapping m4 symbol names to simple expansion text. */ -static const m4_macro m4_macro_table[] = -{ - /* name text min max */ - { "__mpeval__", "", 0, 0 }, - { NULL, NULL, 0, 0 }, -}; - - -void -include_mpeval (m4 *context, m4_module *module, m4_obstack *obs) -{ - m4_install_builtins (context, module, m4_builtin_table); - m4_install_macros (context, module, m4_macro_table); -} - - -/* GMP defines mpq_t as a 1-element array of struct. Therefore, `mpq_t' - is not compatible with `const mpq_t'. */ -typedef mpq_t number; - -static void numb_initialise (void); -static void numb_obstack (m4_obstack *obs, const number value, - const int radix, int min); -static void mpq2mpz (m4 *context, mpz_t z, const number q, const char *noisily); -static void mpz2mpq (number q, const mpz_t z); -static void numb_divide (number *x, number *y); -static void numb_modulo (m4 *context, number *x, number *y); -static void numb_and (m4 *context, number *x, number *y); -static void numb_ior (m4 *context, number *x, number *y); -static void numb_eor (m4 *context, number *x, number *y); -static void numb_not (m4 *context, number *x); -static void numb_lshift (m4 *context, number *x, number *y); -static void numb_rshift (m4 *context, number *x, number *y); -#define numb_urshift(c, x, y) numb_rshift (c, x, y) - - -static number numb_ZERO; -static number numb_ONE; - -static int numb_initialised = 0; - -static void -numb_initialise (void) -{ - if (numb_initialised) - return; - - numb_init (numb_ZERO); - numb_set_si (&numb_ZERO, 0); - - numb_init (numb_ONE); - numb_set_si (&numb_ONE, 1); - - numb_initialised = 1; -} - -static void -numb_obstack (m4_obstack *obs, const number value, const int radix, - int min) -{ - const char *s; - size_t len; - - mpz_t i; - mpz_init (i); - - mpq_get_num (i, value); - s = mpz_get_str (NULL, radix, i); - - if (*s == '-') - { - obstack_1grow (obs, '-'); - s++; - } - len = strlen (s); - for (min -= len; --min >= 0;) - obstack_1grow (obs, '0'); - - obstack_grow (obs, s, len); - - mpq_get_den (i, value); - if (mpz_cmp_si (i, (long) 1) != 0) - { - obstack_1grow (obs, '\\'); - s = mpz_get_str ((char *) 0, radix, i); - obstack_grow (obs, s, strlen (s)); - } - - mpz_clear (i); -} - -#define NOISY "" -#define QUIET (char *)0 - -static void -mpq2mpz (m4 *context, mpz_t z, const number q, const char *noisily) -{ - if (noisily && mpz_cmp_si (mpq_denref (q), (long) 1) != 0) - m4_warn (context, 0, NULL, _("loss of precision in eval: %s"), noisily); - - mpz_div (z, mpq_numref (q), mpq_denref (q)); -} - -static void -mpz2mpq (number q, const mpz_t z) -{ - mpq_set_si (q, (long) 0, (unsigned long) 1); - mpq_set_num (q, z); -} - -static void -numb_divide (number * x, number * y) -{ - mpq_t qres; - mpz_t zres; - - mpq_init (qres); - mpq_div (qres, *x, *y); - - mpz_init (zres); - mpz_div (zres, mpq_numref (qres), mpq_denref (qres)); - mpq_clear (qres); - - mpz2mpq (*x, zres); - mpz_clear (zres); -} - -static void -numb_modulo (m4 *context, number * x, number * y) -{ - mpz_t xx, yy, res; - - /* x should be integral */ - /* y should be integral */ - - mpz_init (xx); - mpq2mpz (context, xx, *x, NOISY); - - mpz_init (yy); - mpq2mpz (context, yy, *y, NOISY); - - mpz_init (res); - mpz_mod (res, xx, yy); - - mpz_clear (xx); - mpz_clear (yy); - - mpz2mpq (*x, res); - mpz_clear (res); -} - -static void -numb_and (m4 *context, number * x, number * y) -{ - mpz_t xx, yy, res; - - /* x should be integral */ - /* y should be integral */ - - mpz_init (xx); - mpq2mpz (context, xx, *x, NOISY); - - mpz_init (yy); - mpq2mpz (context, yy, *y, NOISY); - - mpz_init (res); - mpz_and (res, xx, yy); - - mpz_clear (xx); - mpz_clear (yy); - - mpz2mpq (*x, res); - mpz_clear (res); -} - -static void -numb_ior (m4 *context, number * x, number * y) -{ - mpz_t xx, yy, res; - - /* x should be integral */ - /* y should be integral */ - - mpz_init (xx); - mpq2mpz (context, xx, *x, NOISY); - - mpz_init (yy); - mpq2mpz (context, yy, *y, NOISY); - - mpz_init (res); - mpz_ior (res, xx, yy); - - mpz_clear (xx); - mpz_clear (yy); - - mpz2mpq (*x, res); - mpz_clear (res); -} - -static void -numb_eor (m4 *context, number * x, number * y) -{ - mpz_t xx, yy, res; - - /* x should be integral */ - /* y should be integral */ - - mpz_init (xx); - mpq2mpz (context, xx, *x, NOISY); - - mpz_init (yy); - mpq2mpz (context, yy, *y, NOISY); - - mpz_init (res); - -#if 0 - mpz_xor (res, xx, yy); -#else /* 0 */ - /* a^b = (a|b) & !(a&b) */ - { - mpz_t and_ab, ior_ab, nand_ab; - - mpz_init (ior_ab); - mpz_ior (ior_ab, xx, yy); - - mpz_init (and_ab); - mpz_and (and_ab, xx, yy); - - mpz_init (nand_ab); - mpz_com (nand_ab, and_ab); - - mpz_and (res, ior_ab, nand_ab); - - mpz_clear (and_ab); - mpz_clear (ior_ab); - mpz_clear (nand_ab); - } -#endif /* 0 */ - - mpz_clear (xx); - mpz_clear (yy); - - mpz2mpq (*x, res); - mpz_clear (res); -} - -static void -numb_not (m4 *context, number * x) -{ - mpz_t xx, res; - - /* x should be integral */ - - mpz_init (xx); - mpq2mpz (context, xx, *x, NOISY); - - mpz_init (res); - mpz_com (res, xx); - - mpz_clear (xx); - - mpz2mpq (*x, res); - mpz_clear (res); -} - -static void -numb_lshift (m4 *context, number * x, number * y) -{ - mpz_t xx, yy, res; - - /* x should be integral */ - /* y should be integral */ - - mpz_init (xx); - mpq2mpz (context, xx, *x, NOISY); - - mpz_init (yy); - mpq2mpz (context, yy, *y, NOISY); - - mpz_init (res); - { - /* bug: need to determine if y is too big or negative. */ - long int exp = mpz_get_si (yy); - if (exp >= 0) - { - mpz_mul_2exp (res, xx, (unsigned) exp); - } - else - { - mpz_div_2exp (res, xx, (unsigned) -exp); - } - } - - mpz_clear (xx); - mpz_clear (yy); - - mpz2mpq (*x, res); - mpz_clear (res); -} - -static void -numb_rshift (m4 *context, number * x, number * y) -{ - mpz_t xx, yy, res; - - /* x should be integral */ - /* y should be integral */ - - mpz_init (xx); - mpq2mpz (context, xx, *x, NOISY); - - mpz_init (yy); - mpq2mpz (context, yy, *y, NOISY); - - mpz_init (res); - { - /* FIXME: bug - need to determine if y is too big or negative */ - long int exp = mpz_get_si (yy); - if (exp >= 0) - { - mpz_div_2exp (res, xx, (unsigned) exp); - } - else - { - mpz_mul_2exp (res, xx, (unsigned) -exp); - } - } - - mpz_clear (xx); - mpz_clear (yy); - - mpz2mpq (*x, res); - mpz_clear (res); -} - -#define m4_evaluate builtin_mpeval -#include "evalparse.c" diff --git a/modules/stdlib.c b/modules/stdlib.c deleted file mode 100644 index 708f8c61..00000000 --- a/modules/stdlib.c +++ /dev/null @@ -1,288 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1999-2001, 2006-2010, 2013-2014, 2017 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 . -*/ - -#include - -#include -#if TM_IN_SYS_TIME -# include -#else -# include -#endif -#include - -/* Build using only the exported interfaces, unless NDEBUG is set, in - which case use private symbols to speed things up as much as possible. */ -#ifndef NDEBUG -# include -#else -# include "m4private.h" -#endif - -/* function macros blind side minargs maxargs */ -#define builtin_functions \ - BUILTIN (getcwd, false, false, false, 0, 0 ) \ - BUILTIN (getenv, false, true, false, 1, 1 ) \ - BUILTIN (getlogin, false, false, false, 0, 0 ) \ - BUILTIN (getpid, false, false, false, 0, 0 ) \ - BUILTIN (getppid, false, false, false, 0, 0 ) \ - BUILTIN (getuid, false, false, false, 0, 0 ) \ - BUILTIN (getpwnam, false, true, false, 1, 1 ) \ - BUILTIN (getpwuid, false, true, false, 1, 1 ) \ - BUILTIN (hostname, false, false, false, 0, 0 ) \ - BUILTIN (rand, false, false, false, 0, 0 ) \ - BUILTIN (srand, false, false, false, 0, 1 ) \ - BUILTIN (setenv, false, true, false, 2, 3 ) \ - BUILTIN (unsetenv, false, true, false, 1, 1 ) \ - BUILTIN (uname, false, false, false, 0, 0 ) \ - - -#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN (handler); - builtin_functions -#undef BUILTIN - -static const m4_builtin m4_builtin_table[] = -{ -#define BUILTIN(handler, macros, blind, side, min, max) \ - M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max) - - builtin_functions -#undef BUILTIN - - { NULL, NULL, 0, 0, 0 }, -}; - - -void -include_stdlib (m4 *context, m4_module *module, m4_obstack *obs) -{ - m4_install_builtins (context, module, m4_builtin_table); -} - - -/** - * getcwd() - **/ -M4BUILTIN_HANDLER (getcwd) -{ - /* FIXME - Use gnulib module for arbitrary-length cwd. */ - char buf[1024]; - char *bp; - - bp = getcwd (buf, sizeof buf); - - if (bp != NULL) /* in case of error return null string */ - m4_shipout_string (context, obs, buf, SIZE_MAX, false); -} - -/** - * getenv(NAME) - **/ -M4BUILTIN_HANDLER (getenv) -{ - char *env; - - env = getenv (M4ARG (1)); - - if (env != NULL) - m4_shipout_string (context, obs, env, SIZE_MAX, false); -} - -/** - * setenv(NAME, VALUE, [OVERWRITE]) - **/ -M4BUILTIN_HANDLER (setenv) -{ - int overwrite = 1; - - if (argc >= 4) - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (3), M4ARGLEN (3), - &overwrite)) - return; - - /* TODO - error checking. */ - setenv (M4ARG (1), M4ARG (2), overwrite); -} - -/** - * unsetenv(NAME) - **/ -M4BUILTIN_HANDLER (unsetenv) -{ - /* TODO - error checking. */ - unsetenv (M4ARG (1)); -} - -/** - * getlogin() - **/ -M4BUILTIN_HANDLER (getlogin) -{ - char *login; - - login = getlogin (); - - if (login != NULL) - m4_shipout_string (context, obs, login, SIZE_MAX, false); -} - -/** - * getpid() - **/ -M4BUILTIN_HANDLER (getpid) -{ - m4_shipout_int (obs, getpid ()); -} - -/** - * getppid() - **/ -M4BUILTIN_HANDLER (getppid) -{ - m4_shipout_int (obs, getppid ()); -} - -/** - * getpwnam(NAME) - **/ -M4BUILTIN_HANDLER (getpwnam) -{ - struct passwd *pw; - - pw = getpwnam (M4ARG (1)); - - if (pw != NULL) - { - m4_shipout_string (context, obs, pw->pw_name, SIZE_MAX, true); - obstack_1grow (obs, ','); - m4_shipout_string (context, obs, pw->pw_passwd, SIZE_MAX, true); - obstack_1grow (obs, ','); - m4_shipout_int (obs, pw->pw_uid); - obstack_1grow (obs, ','); - m4_shipout_int (obs, pw->pw_gid); - obstack_1grow (obs, ','); - m4_shipout_string (context, obs, pw->pw_gecos, SIZE_MAX, true); - obstack_1grow (obs, ','); - m4_shipout_string (context, obs, pw->pw_dir, SIZE_MAX, true); - obstack_1grow (obs, ','); - m4_shipout_string (context, obs, pw->pw_shell, SIZE_MAX, true); - } -} - -/** - * getpwuid(UID) - **/ -M4BUILTIN_HANDLER (getpwuid) -{ - struct passwd *pw; - int uid; - - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), - &uid)) - return; - - pw = getpwuid (uid); - - if (pw != NULL) - { - m4_shipout_string (context, obs, pw->pw_name, SIZE_MAX, true); - obstack_1grow (obs, ','); - m4_shipout_string (context, obs, pw->pw_passwd, SIZE_MAX, true); - obstack_1grow (obs, ','); - m4_shipout_int (obs, pw->pw_uid); - obstack_1grow (obs, ','); - m4_shipout_int (obs, pw->pw_gid); - obstack_1grow (obs, ','); - m4_shipout_string (context, obs, pw->pw_gecos, SIZE_MAX, true); - obstack_1grow (obs, ','); - m4_shipout_string (context, obs, pw->pw_dir, SIZE_MAX, true); - obstack_1grow (obs, ','); - m4_shipout_string (context, obs, pw->pw_shell, SIZE_MAX, true); - } -} - -/** - * hostname() - **/ -M4BUILTIN_HANDLER (hostname) -{ - char buf[1024]; - - if (gethostname (buf, sizeof buf) < 0) - return; - - m4_shipout_string (context, obs, buf, SIZE_MAX, false); -} - -/** - * rand() - **/ -M4BUILTIN_HANDLER (rand) -{ - m4_shipout_int (obs, rand ()); -} - -/** - * srand() - **/ -M4BUILTIN_HANDLER (srand) -{ - int seed; - - if (argc == 1) - seed = time (0L) * getpid (); - else - { - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), - M4ARGLEN (1), &seed)) - return; - } - - srand (seed); -} - -/** - * uname() - **/ -M4BUILTIN_HANDLER (uname) -{ - struct utsname ut; - - if (uname (&ut) == 0) - { - m4_shipout_string (context, obs, ut.sysname, SIZE_MAX, true); - obstack_1grow (obs, ','); - m4_shipout_string (context, obs, ut.nodename, SIZE_MAX, true); - obstack_1grow (obs, ','); - m4_shipout_string (context, obs, ut.release, SIZE_MAX, true); - obstack_1grow (obs, ','); - m4_shipout_string (context, obs, ut.version, SIZE_MAX, true); - obstack_1grow (obs, ','); - m4_shipout_string (context, obs, ut.machine, SIZE_MAX, true); - } -} - -/** - * getuid() - **/ -M4BUILTIN_HANDLER (getuid) -{ - m4_shipout_int (obs, getuid ()); -} diff --git a/modules/time.c b/modules/time.c deleted file mode 100644 index 7f64f922..00000000 --- a/modules/time.c +++ /dev/null @@ -1,240 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1999-2001, 2006-2010, 2013-2014, 2017 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 . -*/ - -#include - -#if TM_IN_SYS_TIME -# include -#else -# include -#endif /* TM_IN_SYS_TIME */ - -/* Build using only the exported interfaces, unless NDEBUG is set, in - which case use private symbols to speed things up as much as possible. */ -#ifndef NDEBUG -# include -#else -# include "m4private.h" -#endif - -/* function macros blind side minargs maxargs */ -#define builtin_functions \ - BUILTIN (currenttime, false, false, false, 0, 0 ) \ - BUILTIN (ctime, false, false, false, 0, 1 ) \ - BUILTIN (gmtime, false, true, false, 1, 1 ) \ - BUILTIN (localtime, false, true, false, 1, 1 ) \ - -#define mktime_functions \ - BUILTIN (mktime, false, true, false, 6, 7 ) \ - -#define strftime_functions \ - BUILTIN (strftime, false, true, false, 2, 2 ) \ - - -#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN (handler) - builtin_functions -# if HAVE_MKTIME - mktime_functions -# endif -# if HAVE_STRFTIME - strftime_functions -# endif -#undef BUILTIN - -static const m4_builtin m4_builtin_table[] = -{ -#define BUILTIN(handler, macros, blind, side, min, max) \ - M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max) - - builtin_functions -# if HAVE_MKTIME - mktime_functions -# endif -# if HAVE_STRFTIME - strftime_functions -# endif -#undef BUILTIN - - { NULL, NULL, 0, 0, 0 }, -}; - - -void -include_time (m4 *context, m4_module *module, m4_obstack *obs) -{ - m4_install_builtins (context, module, m4_builtin_table); -} - - - -/** - * currenttime() - **/ -M4BUILTIN_HANDLER (currenttime) -{ - char buf[64]; - time_t now; - int l; - - now = time (0L); - l = sprintf (buf, "%ld", now); - - obstack_grow (obs, buf, l); -} - -/** - * ctime([SECONDS]) - **/ -M4BUILTIN_HANDLER (ctime) -{ - time_t t; - int i; - const char *s; - - if (argc == 2) - { - m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), - &i); - t = i; - } - else - t = time (0L); - - s = ctime (&t); - obstack_grow (obs, s, 24); -} - -static void -format_tm (m4_obstack *obs, struct tm *tm) -{ - m4_shipout_int (obs, tm->tm_sec); - obstack_1grow (obs, ','); - - m4_shipout_int (obs, tm->tm_min); - obstack_1grow (obs, ','); - - m4_shipout_int (obs, tm->tm_hour); - obstack_1grow (obs, ','); - - m4_shipout_int (obs, tm->tm_mday); - obstack_1grow (obs, ','); - - m4_shipout_int (obs, tm->tm_mon); - obstack_1grow (obs, ','); - - m4_shipout_int (obs, tm->tm_year); - obstack_1grow (obs, ','); - - m4_shipout_int (obs, tm->tm_wday); - obstack_1grow (obs, ','); - - m4_shipout_int (obs, tm->tm_yday); - obstack_1grow (obs, ','); - - m4_shipout_int (obs, tm->tm_isdst); -} - -/** - * gmtime(SECONDS) - **/ -M4BUILTIN_HANDLER (gmtime) -{ - time_t t; - int i; - - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), - &i)) - return; - - t = i; - format_tm (obs, gmtime (&t)); -} - -/** - * localtime(SECONDS) - **/ -M4BUILTIN_HANDLER (localtime) -{ - time_t t; - int i; - - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (1), M4ARGLEN (1), - &i)) - return; - - t = i; - format_tm (obs, localtime (&t)); -} - -#if HAVE_MKTIME -/** - * mktime(SEC, MIN, HOUR, MDAY, MONTH, YEAR, [ISDST]) - **/ -M4BUILTIN_HANDLER (mktime) -{ - const m4_call_info *me = m4_arg_info (argv); - struct tm tm; - time_t t; - - if (!m4_numeric_arg (context, me, M4ARG (1), M4ARGLEN (1), &tm.tm_sec)) - return; - if (!m4_numeric_arg (context, me, M4ARG (2), M4ARGLEN (2), &tm.tm_min)) - return; - if (!m4_numeric_arg (context, me, M4ARG (3), M4ARGLEN (3), &tm.tm_hour)) - return; - if (!m4_numeric_arg (context, me, M4ARG (4), M4ARGLEN (4), &tm.tm_mday)) - return; - if (!m4_numeric_arg (context, me, M4ARG (5), M4ARGLEN (5), &tm.tm_mon)) - return; - if (!m4_numeric_arg (context, me, M4ARG (6), M4ARGLEN (6), &tm.tm_year)) - return; - if (M4ARG (7) && !m4_numeric_arg (context, me, M4ARG (7), M4ARGLEN (7), - &tm.tm_isdst)) - return; - - t = mktime (&tm); - - m4_shipout_int (obs, t); -} -#endif /* HAVE_MKTIME */ - -#if HAVE_STRFTIME -/** - * strftime(FORMAT, SECONDS) - **/ -M4BUILTIN_HANDLER (strftime) -{ - struct tm *tm; - time_t t; - char *buf; - int l; - - if (!m4_numeric_arg (context, m4_arg_info (argv), M4ARG (2), M4ARGLEN (2), - &l)) - return; - - t = l; - tm = localtime (&t); - - buf = (char *) obstack_alloc (obs, 1024); - l = strftime (buf, 1024, M4ARG (1), tm); - obstack_grow (obs, buf, l); -} -#endif /* HAVE_STRFTIME */ diff --git a/modules/traditional.c b/modules/traditional.c deleted file mode 100644 index 648cef76..00000000 --- a/modules/traditional.c +++ /dev/null @@ -1,52 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 2000, 2006-2008, 2010, 2013-2014, 2017 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 . -*/ - -#include - -/* Build using only the exported interfaces, unless NDEBUG is set, in - which case use private symbols to speed things up as much as possible. */ -#ifndef NDEBUG -# include -#else -# include "m4private.h" -#endif - -/* A table for mapping m4 symbol names to simple expansion text. */ -static const m4_macro m4_macro_table[] = -{ - /* name text min max */ -#if UNIX - { "unix", "", 0, 0 }, -#elif W32_NATIVE - { "windows", "", 0, 0 }, -#elif OS2 - { "os2", "", 0, 0 }, -#else -# warning Platform macro not provided -#endif - { "__traditional__", "", 0, 0 }, - { NULL, NULL, 0, 0 }, -}; - -void -include_traditional (m4 *context, m4_module *module, m4_obstack *obs) -{ - m4_install_macros (context, module, m4_macro_table); -} diff --git a/po/Makevars b/po/Makevars deleted file mode 100644 index f1bf1501..00000000 --- a/po/Makevars +++ /dev/null @@ -1,44 +0,0 @@ -# Makefile variables for PO directory in any package using GNU gettext. - -# Usually the message domain is the same as the package name. -DOMAIN = $(PACKAGE) - -# These two variables depend on the location of this directory. -subdir = po -top_builddir = .. - -# These options get passed to xgettext. -XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ \ - --flag=_:1:pass-c-format \ - --flag=N_:1:pass-c-format \ - $${end_of_xgettext_options+} - -# This is the copyright holder that gets inserted into the header of the -# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding -# package. (Note that the msgstr strings, extracted from the package's -# sources, belong to the copyright holder of the package.) Translators are -# expected to transfer the copyright for their translations to this person -# or entity, or to disclaim their copyright. The empty string stands for -# the public domain; in this case the translators are expected to disclaim -# their copyright. -COPYRIGHT_HOLDER = Free Software Foundation, Inc. - -# This is the email address or URL to which the translators shall report -# bugs in the untranslated strings: -# - Strings which are not entire sentences, see the maintainer guidelines -# in the GNU gettext documentation, section 'Preparing Strings'. -# - Strings which use unclear terms or require additional context to be -# understood. -# - Strings which make invalid assumptions about notation of date, time or -# money. -# - Pluralisation problems. -# - Incorrect English spelling. -# - Incorrect formatting. -# It can be your email address, or a mailing list address where translators -# can write to without being subscribed, or the URL of a web page through -# which the translators can contact you. -MSGID_BUGS_ADDRESS = bug-m4@gnu.org - -# This is the list of locale categories, beyond LC_MESSAGES, for which the -# message catalogs shall be used. It is usually empty. -EXTRA_LOCALE_CATEGORIES = diff --git a/po/POTFILES.in b/po/POTFILES.in deleted file mode 100644 index cb3767f5..00000000 --- a/po/POTFILES.in +++ /dev/null @@ -1,31 +0,0 @@ -m4/builtin.c -m4/debug.c -m4/gnu/clean-temp.c -m4/gnu/closein.c -m4/gnu/closeout.c -m4/gnu/error.c -m4/gnu/obstack.c -m4/gnu/quotearg.c -m4/gnu/regcomp.c -m4/gnu/verror.c -m4/gnu/xalloc-die.c -m4/gnu/xprintf.c -m4/input.c -m4/macro.c -m4/module.c -m4/output.c -m4/path.c -m4/symtab.c -m4/utility.c -modules/evalparse.c -modules/format.c -modules/gnu.c -modules/m4.c -modules/mpeval.c -modules/traditional.c -src/freeze.c -src/getopt.c -src/main.c -src/stackovf.c -src/version-etc.c -src/xstrtol-error.c diff --git a/src/freeze.c b/src/freeze.c deleted file mode 100644 index 426e34b5..00000000 --- a/src/freeze.c +++ /dev/null @@ -1,1000 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 2004-2010, 2013-2014, 2017 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 . -*/ - -/* This module handles frozen files. */ - -#include - -#include "m4.h" - -#include "binary-io.h" -#include "close-stream.h" -#include "quotearg.h" -#include "verify.h" -#include "xmemdup0.h" - -static void produce_mem_dump (FILE *, const char *, size_t); -static void produce_resyntax_dump (m4 *, FILE *); -static void produce_syntax_dump (FILE *, m4_syntax_table *, char); -static void produce_module_dump (m4 *, FILE *, m4_module *); -static void produce_symbol_dump (m4 *, FILE *, m4_symbol_table *); -static void *dump_symbol_CB (m4_symbol_table *, const char *, - size_t, m4_symbol *, void *); -static void issue_expect_message (m4 *, int); -static int decode_char (m4 *, FILE *, bool *); - - -/* Dump an ASCII-encoded representation of LEN bytes at MEM to FILE. - MEM may contain embedded NUL characters. */ -static void -produce_mem_dump (FILE *file, const char *mem, size_t len) -{ - char *quoted = quotearg_style_mem (escape_quoting_style, mem, len); - /* Any errors will be detected by ferror later. */ - fwrite (quoted, strlen (quoted), 1, file); -} - - -/* Produce the 'R14\nPOSIX_EXTENDED\n' frozen file dump of the current - default regular expression syntax. Note that it would be a little - faster to use the encoded syntax in this format as used by re_compile(), - but the representation of RE_SYNTAX_POSIX_EXTENDED may change in - future (or alternative) implementations of re_compile, so we use an - unencoded representation here. */ - -static void -produce_resyntax_dump (m4 *context, FILE *file) -{ - int code = m4_get_regexp_syntax_opt (context); - - /* Don't dump default syntax code (`0' for GNU_EMACS). */ - if (code) - { - const char *resyntax = m4_regexp_syntax_decode (code); - - if (!resyntax) - m4_error (context, EXIT_FAILURE, 0, NULL, - _("invalid regexp syntax code `%d'"), code); - - /* No need to use produce_mem_dump, since we know all resyntax - names are already ASCII-encoded. */ - xfprintf (file, "R%zu\n%s\n", strlen (resyntax), resyntax); - } -} - -static void -produce_syntax_dump (FILE *file, m4_syntax_table *syntax, char ch) -{ - char buf[UCHAR_MAX + 1]; - int code = m4_syntax_code (ch); - int count = 0; - int i; - - for (i = 0; i < UCHAR_MAX + 1; ++i) - if (m4_has_syntax (syntax, i, code) && code != syntax->orig[i]) - buf[count++] = i; - - /* If code falls in M4_SYNTAX_MASKS, then we must treat it - specially, since it will not be found in syntax->orig. */ - if (count == 1 - && ((code == M4_SYNTAX_RQUOTE && *buf == *DEF_RQUOTE) - || (code == M4_SYNTAX_ECOMM && *buf == *DEF_ECOMM))) - return; - - if (count || (code & M4_SYNTAX_MASKS)) - { - xfprintf (file, "S%c%d\n", ch, count); - produce_mem_dump (file, buf, count); - fputc ('\n', file); - } -} - -/* Store the debug mode in textual format. */ -static void -produce_debugmode_state (FILE *file, int flags) -{ - /* This code tracks the number of bits in M4_DEBUG_TRACE_VERBOSE. */ - char str[15]; - int offset = 0; - verify ((1 << (sizeof str - 1)) - 1 == M4_DEBUG_TRACE_VERBOSE); - if (flags & M4_DEBUG_TRACE_ARGS) - str[offset++] = 'a'; - if (flags & M4_DEBUG_TRACE_EXPANSION) - str[offset++] = 'e'; - if (flags & M4_DEBUG_TRACE_QUOTE) - str[offset++] = 'q'; - if (flags & M4_DEBUG_TRACE_ALL) - str[offset++] = 't'; - if (flags & M4_DEBUG_TRACE_LINE) - str[offset++] = 'l'; - if (flags & M4_DEBUG_TRACE_FILE) - str[offset++] = 'f'; - if (flags & M4_DEBUG_TRACE_PATH) - str[offset++] = 'p'; - if (flags & M4_DEBUG_TRACE_CALL) - str[offset++] = 'c'; - if (flags & M4_DEBUG_TRACE_INPUT) - str[offset++] = 'i'; - if (flags & M4_DEBUG_TRACE_CALLID) - str[offset++] = 'x'; - if (flags & M4_DEBUG_TRACE_MODULE) - str[offset++] = 'm'; - if (flags & M4_DEBUG_TRACE_STACK) - str[offset++] = 's'; - if (flags & M4_DEBUG_TRACE_DEREF) - str[offset++] = 'd'; - if (flags & M4_DEBUG_TRACE_OUTPUT_DUMPDEF) - str[offset++] = 'o'; - str[offset] = '\0'; - if (offset) - xfprintf (file, "d%d\n%s\n", offset, str); -} - -/* The modules must be dumped in the order in which they will be - reloaded from the frozen file. We store handles in a push - down stack, so we need to dump them in the reverse order to that. */ -static void -produce_module_dump (m4 *context, FILE *file, m4_module *module) -{ - const char *name = m4_get_module_name (module); - size_t len = strlen (name); - - module = m4_module_next (context, module); - if (module) - produce_module_dump (context, file, module); - - xfprintf (file, "M%zu\n", len); - produce_mem_dump (file, name, len); - fputc ('\n', file); -} - -/* Process all entries in one bucket, from the last to the first. - This order ensures that, at reload time, pushdef's will be - executed with the oldest definitions first. */ -static void -produce_symbol_dump (m4 *context, FILE *file, m4_symbol_table *symtab) -{ - if (m4_symtab_apply (symtab, true, dump_symbol_CB, file)) - assert (false); -} - -/* Given a stack of symbol values starting with VALUE, destructively - reverse the stack and return the pointer to what was previously the - last value in the stack. VALUE may be NULL. The symbol table that - owns the value stack should not be modified or consulted until this - is called again to undo the effect. */ -static m4_symbol_value * -reverse_symbol_value_stack (m4_symbol_value *value) -{ - m4_symbol_value *result = NULL; - m4_symbol_value *next; - while (value) - { - next = VALUE_NEXT (value); - VALUE_NEXT (value) = result; - result = value; - value = next; - } - return result; -} - -/* Dump the stack of values for SYMBOL, with name SYMBOL_NAME and - length LEN, located in SYMTAB. USERDATA is interpreted as the - FILE* to dump to. */ -static void * -dump_symbol_CB (m4_symbol_table *symtab, const char *symbol_name, size_t len, - m4_symbol *symbol, void *userdata) -{ - FILE *file = (FILE *) userdata; - m4_symbol_value *value; - m4_symbol_value *last; - - last = value = reverse_symbol_value_stack (m4_get_symbol_value (symbol)); - while (value) - { - m4_module *module = VALUE_MODULE (value); - const char *module_name = module ? m4_get_module_name (module) : NULL; - size_t module_len = module_name ? strlen (module_name) : 0; - - if (m4_is_symbol_value_text (value)) - { - const char *text = m4_get_symbol_value_text (value); - size_t text_len = m4_get_symbol_value_len (value); - xfprintf (file, "T%zu,%zu", len, text_len); - if (module) - xfprintf (file, ",%zu", module_len); - fputc ('\n', file); - - produce_mem_dump (file, symbol_name, len); - fputc ('\n', file); - produce_mem_dump (file, text, text_len); - fputc ('\n', file); - if (module) - { - produce_mem_dump (file, module_name, module_len); - fputc ('\n', file); - } - } - else if (m4_is_symbol_value_func (value)) - { - const m4_builtin *bp = m4_get_symbol_value_builtin (value); - size_t bp_len; - if (bp == NULL) - assert (!"INTERNAL ERROR: builtin not found in builtin table!"); - bp_len = strlen (bp->name); - - xfprintf (file, "F%zu,%zu", len, bp_len); - if (module) - xfprintf (file, ",%zu", module_len); - fputc ('\n', file); - - produce_mem_dump (file, symbol_name, len); - fputc ('\n', file); - produce_mem_dump (file, bp->name, bp_len); - fputc ('\n', file); - if (module) - { - produce_mem_dump (file, module_name, module_len); - fputc ('\n', file); - } - } - else if (m4_is_symbol_value_placeholder (value)) - ; /* Nothing to do for a builtin we couldn't reload earlier. */ - else - assert (!"dump_symbol_CB"); - value = VALUE_NEXT (value); - } - reverse_symbol_value_stack (last); - if (m4_get_symbol_traced (symbol)) - xfprintf (file, "t%zu\n%s\n", len, symbol_name); - return NULL; -} - -/* Produce a frozen state to the given file NAME. */ -void -produce_frozen_state (m4 *context, const char *name) -{ - FILE *file = fopen (name, O_BINARY ? "wb" : "w"); - const char *str; - const m4_string_pair *pair; - - if (!file) - { - m4_error (context, 0, errno, NULL, _("cannot open %s"), - quotearg_style (locale_quoting_style, name)); - return; - } - - /* Write a recognizable header. */ - - xfprintf (file, "# This is a frozen state file generated by GNU %s %s\n", - PACKAGE, VERSION); - fputs ("V2\n", file); - - /* Dump quote delimiters. */ - pair = m4_get_syntax_quotes (M4SYNTAX); - if (STRNEQ (pair->str1, DEF_LQUOTE) || STRNEQ (pair->str2, DEF_RQUOTE)) - { - xfprintf (file, "Q%zu,%zu\n", pair->len1, pair->len2); - produce_mem_dump (file, pair->str1, pair->len1); - fputc ('\n', file); - produce_mem_dump (file, pair->str2, pair->len2); - fputc ('\n', file); - } - - /* Dump comment delimiters. */ - pair = m4_get_syntax_comments (M4SYNTAX); - if (STRNEQ (pair->str1, DEF_BCOMM) || STRNEQ (pair->str2, DEF_ECOMM)) - { - xfprintf (file, "C%zu,%zu\n", pair->len1, pair->len2); - produce_mem_dump (file, pair->str1, pair->len1); - fputc ('\n', file); - produce_mem_dump (file, pair->str2, pair->len2); - fputc ('\n', file); - } - - /* Dump regular expression syntax. */ - produce_resyntax_dump (context, file); - - /* Dump syntax table. */ - str = "I@WLBOD${}SA(),RE"; - while (*str) - produce_syntax_dump (file, M4SYNTAX, *str++); - - /* Dump debugmode state. */ - produce_debugmode_state (file, m4_get_debug_level_opt (context)); - - /* Dump all loaded modules. */ - produce_module_dump (context, file, m4_module_next (context, NULL)); - - /* Dump all symbols. */ - produce_symbol_dump (context, file, M4SYMTAB); - - /* Let diversions be issued from output.c module, its cleaner to have this - piece of code there. */ - m4_freeze_diversions (context, file); - - /* All done. */ - - fputs ("# End of frozen state file\n", file); - if (close_stream (file) != 0) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("unable to create frozen state")); -} - -/* Issue a message saying that some character is an EXPECTED character. */ -static void -issue_expect_message (m4 *context, int expected) -{ - if (expected == '\n') - m4_error (context, EXIT_FAILURE, 0, NULL, - _("expecting line feed in frozen file")); - else - m4_error (context, EXIT_FAILURE, 0, NULL, - _("expecting character `%c' in frozen file"), expected); -} - - -/* Reload frozen state. */ - -/* Read the next character from the IN stream. Various escape - sequences are converted, and returned. EOF is returned if the end - of file is reached whilst reading the character, or on an - unrecognized escape sequence. */ - -static int -decode_char (m4 *context, FILE *in, bool *advance_line) -{ - int ch = getc (in); - int next; - int value = 0; - - if (*advance_line) - { - m4_set_current_line (context, m4_get_current_line (context) + 1); - *advance_line = false; - } - - while (ch == '\\') - { - ch = getc (in); - switch (ch) - { - case 'a': return '\a'; - case 'b': return '\b'; - case 'f': return '\f'; - case 'n': return '\n'; - case 'r': return '\r'; - case 't': return '\t'; - case 'v': return '\v'; - case '\\': return '\\'; - - case '\n': - ch = getc (in); - m4_set_current_line (context, m4_get_current_line (context) + 1); - continue; - - case 'x': case 'X': - next = getc (in); - if (next >= '0' && next <= '9') - ch = (next - '0') * 16; - else if (next >= 'a' && next <= 'f') - ch = (next - 'a' + 10) * 16; - else if (next >= 'A' && next <= 'F') - ch = (next - 'A' + 10) * 16; - else - return EOF; - next = getc (in); - if (next >= '0' && next <= '9') - ch += next - '0'; - else if (next >= 'a' && next <= 'f') - ch += next - 'a' + 10; - else if (next >= 'A' && next <= 'F') - ch += next - 'A' + 10; - else - return EOF; - return ch; - case '0': case '1': case '2': case '3': - value = ch - '0'; - ch = getc (in); - /* fall through */ - case '4': case '5': case '6': case '7': - if (ch >= '0' && ch <= '7') - { - value = value * 8 + ch - '0'; - ch = getc (in); - } - else - { - ungetc (ch, in); - return value; - } - if (ch >= '0' && ch <= '7') - value = value * 8 + ch - '0'; - else - ungetc (ch, in); - return value; - - default: - return EOF; - } - } - - if (ch == '\n') - *advance_line = true; - return ch; -} - - -/* Reload state from the given file NAME. We are seeking speed, - here. */ - -void -reload_frozen_state (m4 *context, const char *name) -{ - FILE *file = NULL; - char *filepath; - int version; - int character; - int operation; - char syntax; - char *string[3]; - size_t allocated[3]; - int number[3] = {0}; - bool advance_line = true; - -#define GET_CHARACTER \ - do \ - { \ - if (advance_line) \ - { \ - m4_set_current_line (context, \ - m4_get_current_line (context) + 1); \ - advance_line = false; \ - } \ - character = getc (file); \ - if (character == '\n') \ - advance_line = true; \ - } \ - while (0) - -#define GET_NUMBER(Number, AllowNeg) \ - do \ - { \ - unsigned int n = 0; \ - while (isdigit (character) && n <= INT_MAX / 10) \ - { \ - n = 10 * n + character - '0'; \ - GET_CHARACTER; \ - } \ - if (((AllowNeg) ? INT_MIN: INT_MAX) < n \ - || isdigit (character)) \ - m4_error (context, EXIT_FAILURE, 0, NULL, \ - _("integer overflow in frozen file")); \ - (Number) = n; \ - } \ - while (0) - -#define GET_STRING(File, Buf, BufSize, StrLen, UseChar) \ - do \ - { \ - size_t len = (StrLen); \ - char *p; \ - int ch; \ - if (UseChar) \ - { \ - ungetc (character, File); \ - if (advance_line) \ - { \ - assert (character == '\n'); \ - advance_line = false; \ - } \ - } \ - CHECK_ALLOCATION ((Buf), (BufSize), len); \ - p = (Buf); \ - while (len-- > 0) \ - { \ - ch = (version > 1 \ - ? decode_char (context, File, &advance_line) \ - : getc (File)); \ - if (ch == EOF) \ - m4_error (context, EXIT_FAILURE, 0, NULL, \ - _("premature end of frozen file")); \ - *p++ = ch; \ - } \ - *p = '\0'; \ - GET_CHARACTER; \ - while (version > 1 && character == '\\') \ - { \ - GET_CHARACTER; \ - VALIDATE ('\n'); \ - GET_CHARACTER; \ - } \ - } \ - while (0) - -#define VALIDATE(Expected) \ - do \ - { \ - if (character != (Expected)) \ - issue_expect_message (context, (Expected)); \ - } \ - while (0) - -#define CHECK_ALLOCATION(Where, Allocated, Needed) \ - do \ - { \ - if ((Needed) + 1 > (Allocated)) \ - { \ - free (Where); \ - (Allocated) = (Needed) + 1; \ - (Where) = xcharalloc (Allocated); \ - } \ - } \ - while (0) - - /* Skip comments (`#' at beginning of line) and blank lines, setting - character to the next directive or to EOF. */ - -#define GET_DIRECTIVE \ - do \ - { \ - GET_CHARACTER; \ - if (character == '#') \ - { \ - while (character != EOF && character != '\n') \ - GET_CHARACTER; \ - VALIDATE ('\n'); \ - } \ - } \ - while (character == '\n') - - filepath = m4_path_search (context, name, NULL); - file = m4_fopen (context, filepath, "r"); - if (file == NULL) - m4_error (context, EXIT_FAILURE, errno, NULL, _("cannot open %s"), - quotearg_style (locale_quoting_style, name)); - m4_set_current_file (context, name); - - allocated[0] = 100; - string[0] = xcharalloc (allocated[0]); - allocated[1] = 100; - string[1] = xcharalloc (allocated[1]); - allocated[2] = 100; - string[2] = xcharalloc (allocated[2]); - - /* Validate format version. Accept both `1' (m4 1.3 and 1.4.x) and - `2' (m4 2.0). */ - GET_DIRECTIVE; - VALIDATE ('V'); - GET_CHARACTER; - GET_NUMBER (version, false); - switch (version) - { - case 2: - break; - case 1: - m4__module_open (context, "m4", NULL); - if (m4_get_posixly_correct_opt (context)) - m4__module_open (context, "traditional", NULL); - else - m4__module_open (context, "gnu", NULL); - /* Disable { and } categories, since ${11} was not supported in - 1.4.x. */ - m4_set_syntax (M4SYNTAX, 'O', '+', "{}", 2); - break; - default: - if (version > 2) - m4_error (context, EXIT_MISMATCH, 0, NULL, - _("frozen file version %d greater than max supported of 2"), - version); - else - m4_error (context, EXIT_FAILURE, 0, NULL, - _("ill-formed frozen file, version directive expected")); - } - VALIDATE ('\n'); - - GET_DIRECTIVE; - while (character != EOF) - { - switch (character) - { - default: - m4_error (context, EXIT_FAILURE, 0, NULL, - _("ill-formed frozen file, unknown directive %c"), - character); - - case 'd': - /* Set debugmode flags. */ - if (version < 2) - { - /* 'd' operator is not supported in format version 1. */ - m4_error (context, EXIT_FAILURE, 0, NULL, _("\ -ill-formed frozen file, version 2 directive `%c' encountered"), 'd'); - } - - GET_CHARACTER; - GET_NUMBER (number[0], false); - VALIDATE ('\n'); - GET_STRING (file, string[0], allocated[0], number[0], false); - VALIDATE ('\n'); - - if (m4_debug_decode (context, string[0], number[0]) < 0) - m4_error (context, EXIT_FAILURE, 0, NULL, - _("unknown debug mode %s"), - quotearg_style_mem (locale_quoting_style, string[0], - number[0])); - break; - - case 'F': - GET_CHARACTER; - - /* Get string lengths. */ - - GET_NUMBER (number[0], false); - VALIDATE (','); - GET_CHARACTER; - GET_NUMBER (number[1], false); - - if (character == ',') - { - if (version > 1) - { - /* 'F' operator accepts an optional third argument for - format versions 2 or later. */ - GET_CHARACTER; - GET_NUMBER (number[2], false); - } - else - /* 3 argument 'F' operations are invalid for format - version 1. */ - m4_error (context, EXIT_FAILURE, 0, NULL, _("\ -ill-formed frozen file, version 2 directive `%c' encountered"), 'F'); - } - else - { - number[2] = 0; - } - - VALIDATE ('\n'); - - - /* Get string contents. */ - - GET_STRING (file, string[0], allocated[0], number[0], false); - if (version > 1) - { - VALIDATE ('\n'); - GET_CHARACTER; - } - GET_STRING (file, string[1], allocated[1], number[1], true); - if (version > 1 && number[2]) - { - VALIDATE ('\n'); - GET_CHARACTER; - } - GET_STRING (file, string[2], allocated[2], number[2], true); - VALIDATE ('\n'); - - /* Enter a macro having a builtin function as a definition. */ - { - m4_module *module = NULL; - m4_symbol_value *token; - - // Builtins cannot contain a NUL byte. - if (strlen (string[1]) < number[1]) - m4_error (context, EXIT_FAILURE, 0, NULL, _("\ -ill-formed frozen file, invalid builtin %s encountered"), - quotearg_style_mem (locale_quoting_style, string[1], - number[1])); - if (number[2] > 0) - { - if (strlen (string[2]) < number[2]) - m4_error (context, EXIT_FAILURE, 0, NULL, _("\ -ill-formed frozen file, invalid module %s encountered"), - quotearg_style_mem (locale_quoting_style, - string[2], number[2])); - module = m4__module_find (context, string[2]); - } - token = m4_builtin_find_by_name (context, module, string[1]); - - if (token == NULL) - { - token = (m4_symbol_value *) xzalloc (sizeof *token); - m4_set_symbol_value_placeholder (token, xstrdup (string[1])); - VALUE_MODULE (token) = module; - VALUE_MIN_ARGS (token) = 0; - VALUE_MAX_ARGS (token) = -1; - } - m4_symbol_pushdef (M4SYMTAB, string[0], number[0], token); - } - break; - - case 'M': - - /* Load a module, but *without* perturbing the symbol table. - Note that any expansion from loading the module which would - have been seen when loading it originally is discarded - when loading it from a frozen file. */ - - if (version < 2) - { - /* 'M' operator is not supported in format version 1. */ - m4_error (context, EXIT_FAILURE, 0, NULL, _("\ -ill-formed frozen file, version 2 directive `%c' encountered"), 'M'); - } - - GET_CHARACTER; - GET_NUMBER (number[0], false); - VALIDATE ('\n'); - GET_STRING (file, string[0], allocated[0], number[0], false); - VALIDATE ('\n'); - - if (strlen (string[0]) < number[0]) - m4_error (context, EXIT_FAILURE, 0, NULL, _("\ -ill-formed frozen file, invalid module %s encountered"), - quotearg_style_mem (locale_quoting_style, - string[0], number[0])); - m4__module_open (context, string[0], NULL); - - break; - - case 'R': - - if (version < 2) - { - /* 'R' operator is not supported in format version 1. */ - m4_error (context, EXIT_FAILURE, 0, NULL, _("\ -ill-formed frozen file, version 2 directive `%c' encountered"), 'R'); - } - - GET_CHARACTER; - GET_NUMBER (number[0], false); - VALIDATE ('\n'); - GET_STRING (file, string[0], allocated[0], number[0], false); - VALIDATE ('\n'); - - m4_set_regexp_syntax_opt (context, - m4_regexp_syntax_encode (string[0])); - if (m4_get_regexp_syntax_opt (context) < 0 - || strlen (string[0]) < number[0]) - { - m4_error (context, EXIT_FAILURE, 0, NULL, - _("bad syntax-spec %s"), - quotearg_style_mem (locale_quoting_style, string[0], - number[0])); - } - - break; - - case 'S': - - if (version < 2) - { - /* 'S' operator is not supported in format version 1. */ - m4_error (context, EXIT_FAILURE, 0, NULL, _("\ -ill-formed frozen file, version 2 directive `%c' encountered"), 'S'); - } - - GET_CHARACTER; - syntax = character; - GET_CHARACTER; - GET_NUMBER (number[0], false); - VALIDATE ('\n'); - GET_STRING (file, string[0], allocated[0], number[0], false); - - /* Syntax under M4_SYNTAX_MASKS is handled specially; all - other characters are additive. */ - if ((m4_set_syntax (M4SYNTAX, syntax, - (m4_syntax_code (syntax) & M4_SYNTAX_MASKS - ? '=' : '+'), string[0], number[0]) < 0) - && (syntax != '\0')) - { - m4_error (context, 0, 0, NULL, - _("undefined syntax code %c"), syntax); - } - break; - - case 't': - /* Trace a macro name. */ - if (version < 2) - { - /* 't' operator is not supported in format version 1. */ - m4_error (context, EXIT_FAILURE, 0, NULL, _("\ -ill-formed frozen file, version 2 directive `%c' encountered"), 't'); - } - - GET_CHARACTER; - GET_NUMBER (number[0], false); - VALIDATE ('\n'); - GET_STRING (file, string[0], allocated[0], number[0], false); - VALIDATE ('\n'); - - m4_set_symbol_name_traced (M4SYMTAB, string[0], number[0], true); - - break; - - case 'C': - case 'D': - case 'Q': - operation = character; - GET_CHARACTER; - - /* Get string lengths. */ - - if (operation == 'D' && character == '-') - { - /* Accept a negative diversion number. */ - GET_CHARACTER; - GET_NUMBER (number[0], true); - number[0] = -number[0]; - } - else - GET_NUMBER (number[0], false); - VALIDATE (','); - GET_CHARACTER; - GET_NUMBER (number[1], false); - VALIDATE ('\n'); - - /* Get string contents. */ - if (operation != 'D') - { - GET_STRING (file, string[0], allocated[0], number[0], false); - if (version > 1) - { - VALIDATE ('\n'); - GET_CHARACTER; - } - } - else - GET_CHARACTER; - GET_STRING (file, string[1], allocated[1], number[1], true); - VALIDATE ('\n'); - - /* Act according to operation letter. */ - - switch (operation) - { - case 'C': - - /* Change comment strings. */ - - m4_set_comment (M4SYNTAX, string[0], number[0], string[1], - number[1]); - break; - - case 'D': - - /* Select a diversion and add a string to it. */ - - m4_make_diversion (context, number[0]); - if (number[1] > 0) - m4_output_text (context, string[1], number[1]); - break; - - case 'Q': - - /* Change quote strings. */ - - m4_set_quotes (M4SYNTAX, string[0], number[0], string[1], - number[1]); - break; - - default: - - /* Cannot happen. */ - - break; - } - break; - - case 'T': - GET_CHARACTER; - - /* Get string lengths. */ - - GET_NUMBER (number[0], false); - VALIDATE (','); - GET_CHARACTER; - GET_NUMBER (number[1], false); - - if (character == ',') - { - if (version > 1) - { - /* 'T' operator accepts an optional third argument for - format versions 2 or later. */ - GET_CHARACTER; - GET_NUMBER (number[2], false); - } - else - { - /* 3 argument 'T' operations are invalid for format - version 1. */ - m4_error (context, EXIT_FAILURE, 0, NULL, _("\ -ill-formed frozen file, version 2 directive `%c' encountered"), 'T'); - } - } - else - number[2] = 0; - - VALIDATE ('\n'); - - /* Get string contents. */ - GET_STRING (file, string[0], allocated[0], number[0], false); - if (version > 1) - { - VALIDATE ('\n'); - GET_CHARACTER; - } - GET_STRING (file, string[1], allocated[1], number[1], true); - if (version > 1 && number[2]) - { - VALIDATE ('\n'); - GET_CHARACTER; - } - GET_STRING (file, string[2], allocated[2], number[2], true); - VALIDATE ('\n'); - - /* Enter a macro having an expansion text as a definition. */ - { - m4_symbol_value *token; - m4_module *module = NULL; - - token = (m4_symbol_value *) xzalloc (sizeof *token); - if (number[2] > 0) - { - if (strlen (string[2]) < number[2]) - m4_error (context, EXIT_FAILURE, 0, NULL, _("\ -ill-formed frozen file, invalid module %s encountered"), - quotearg_style_mem (locale_quoting_style, - string[2], number[2])); - module = m4__module_find (context, string[2]); - } - - m4_set_symbol_value_text (token, xmemdup0 (string[1], number[1]), - number[1], 0); - VALUE_MODULE (token) = module; - VALUE_MAX_ARGS (token) = -1; - - m4_symbol_pushdef (M4SYMTAB, string[0], number[0], token); - } - break; - - } - GET_DIRECTIVE; - } - - free (string[0]); - free (string[1]); - free (string[2]); - if (close_stream (file) != 0) - m4_error (context, EXIT_FAILURE, errno, NULL, - _("unable to read frozen state")); - m4_set_current_file (context, NULL); - m4_set_current_line (context, 0); - -#undef GET_STRING -#undef GET_CHARACTER -#undef GET_NUMBER -#undef VALIDATE -#undef CHECK_ALLOCATION -#undef GET_DIRECTIVE -} diff --git a/src/m4.h b/src/m4.h deleted file mode 100644 index acd8fa9b..00000000 --- a/src/m4.h +++ /dev/null @@ -1,43 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1989-1994, 2006-2007, 2010, 2013-2014, 2017 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 . -*/ - -#ifndef M4_H -#define M4_H - -#include - -#include "m4private.h" - -#include "gettext.h" - -/* Error handling. */ -#ifdef USE_STACKOVF -void setup_stackovf_trap (char *const *, char *const *, - void (*handler) (void)); -void stackovf_exit (void); -#endif - - -/* File: freeze.c --- frozen state files. */ - -void produce_frozen_state (m4 *context, const char *); -void reload_frozen_state (m4 *context, const char *); - -#endif /* M4_H */ diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 4b897e34..00000000 --- a/src/main.c +++ /dev/null @@ -1,762 +0,0 @@ -/* GNU m4 -- A simple macro processor - - Copyright (C) 1989-1994, 1999-2000, 2003-2010, 2013-2014, 2017 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 . -*/ - -#include - -#include - -#include "m4.h" - -#include "closein.h" -#include "configmake.h" -#include "getopt.h" -#include "propername.h" -#include "quotearg.h" -#include "version-etc.h" -#include "xstrtol.h" - -#define AUTHORS \ - proper_name_utf8 ("Rene' Seindal", "Ren\xc3\xa9 Seindal"), \ - proper_name ("Gary V. Vaughan"), \ - proper_name ("Eric Blake") - -typedef struct deferred -{ - struct deferred *next; - int code; /* deferred optchar */ - const char *value; -} deferred; - - -/* Error handling functions. */ - -#ifdef USE_STACKOVF - -/* Tell user stack overflowed and abort. */ -static void -stackovf_handler (void) -{ - /* FIXME - calling gettext and error inside a signal handler is dangerous, - since these functions invoke functions that are not signal-safe. We - are sort of justified by the fact that we will exit and never return, - but this should really be fixed. */ - error (EXIT_FAILURE, 0, _("stack overflow (infinite define recursion?)")); -} - -#endif /* USE_STACKOVF */ - - - -/* Print a usage message and exit with STATUS. */ -static void -usage (int status) -{ - if (status != EXIT_SUCCESS) - xfprintf (stderr, _("Try `%s --help' for more information.\n"), - m4_get_program_name ()); - else - { - xprintf (_("Usage: %s [OPTION]... [FILE]...\n"), m4_get_program_name ()); - fputs (_("\ -Process macros in FILEs.\n\ -If no FILE or if FILE is `-', standard input is read. If no FILE, and both\n\ -standard input and standard error are terminals, -i is implied.\n\ -"), stdout); - puts (""); - fputs (_("\ -Mandatory or optional arguments to long options are mandatory or optional\n\ -for short options too.\n\ -\n\ -Operation modes:\n\ - --help display this help and exit\n\ - --version output version information and exit\n\ -"), stdout); - fputs (_("\ - -b, --batch buffer output, process interrupts\n\ - -c, --discard-comments do not copy comments to the output\n\ - -E, --fatal-warnings once: warnings become errors, twice: stop\n\ - execution at first error\n\ - -i, --interactive unbuffer output, ignore interrupts\n\ - -P, --prefix-builtins force a `m4_' prefix to all builtins\n\ - -Q, --quiet, --silent suppress some warnings for builtins\n\ - -r, --regexp-syntax[=SPEC] set default regexp syntax to SPEC [GNU_M4]\n\ - --safer disable potentially unsafe builtins\n\ - -W, --warnings enable all warnings\n\ -"), stdout); - puts (""); - fputs (_("\ -SPEC is any one of:\n\ - AWK, BASIC, BSD_M4, ED, EMACS, EXTENDED, GNU_AWK, GNU_EGREP, GNU_M4,\n\ - GREP, POSIX_AWK, POSIX_EGREP, MINIMAL, MINIMAL_BASIC, SED.\n\ -"), stdout); - puts (""); - fputs (_("\ -Preprocessor features:\n\ - -B, --prepend-include=DIR add DIR to include path before `.'\n\ - -D, --define=NAME[=VALUE] define NAME as having VALUE, or empty\n\ - --import-environment import all environment variables as macros\n\ - -I, --include=DIR add DIR to include path after `.'\n\ -"), stdout); - fputs (_("\ - --popdef=NAME popdef NAME\n\ - -p, --pushdef=NAME[=VALUE] pushdef NAME as having VALUE, or empty\n\ - -s, --synclines short for --syncoutput=1\n\ - --syncoutput[=STATE] set generation of `#line NUM \"FILE\"' lines\n\ - to STATE (0=off, 1=on, default 0)\n\ - -U, --undefine=NAME undefine NAME\n\ -"), stdout); - puts (""); - fputs (_("\ -Limits control:\n\ - -g, --gnu override -G to re-enable GNU extensions\n\ - -G, --traditional, --posix suppress all GNU extensions\n\ - -L, --nesting-limit=NUMBER change artificial nesting limit [1024]\n\ -"), stdout); - puts (""); - fputs (_("\ -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\ -"), stdout); - puts (""); - fputs (_("\ -Debugging:\n\ - -d, --debug[=[-|+]FLAGS], --debugmode[=[-|+]FLAGS]\n\ - set debug level (no FLAGS implies `+adeq')\n\ - --debugfile[=FILE] redirect debug and trace output to FILE\n\ - (default stderr, discard if empty string)\n\ - -l, --debuglen=NUM restrict macro tracing size\n\ - -t, --trace=NAME, --traceon=NAME\n\ - trace NAME when it is defined\n\ - --traceoff=NAME no longer trace NAME\n\ -"), stdout); - puts (""); - fputs (_("\ -FLAGS is any of:\n\ - a show actual arguments in trace\n\ - c show collection line in trace\n\ - d warn when dereferencing undefined macros (default on unless -E)\n\ - e show expansion in trace\n\ - f include current input file name in trace and debug\n\ - i show changes in input files in debug\n\ - l include current input line number in trace and debug\n\ -"), stdout); - fputs (_("\ - m show module information in trace, debug, and dumpdef\n\ - o output dumpdef to stderr rather than debug file\n\ - p show results of path searches in debug\n\ - q quote values in dumpdef and trace, useful with a or e\n\ - s show full stack of pushdef values in dumpdef\n\ - t trace all macro calls, regardless of per-macro traceon state\n\ - x include unique macro call id in trace, useful with c\n\ - V shorthand for all of the above flags\n\ -"), stdout); - puts (""); - fputs (_("\ -If defined, the environment variable `M4PATH' is a colon-separated list\n\ -of directories included after any specified by `-I' or `-B'. The\n\ -environment variable `POSIXLY_CORRECT' implies -G -Q; otherwise GNU\n\ -extensions are enabled by default.\n\ -"), stdout); - puts (""); - fputs (_("\ -Exit status is 0 for success, 1 for failure, 63 for frozen file version\n\ -mismatch, or whatever value was passed to the m4exit macro.\n\ -"), stdout); - emit_bug_reporting_address (); - } - exit (status); -} - -/* For long options that have no equivalent short option, use a - non-character as a pseudo short option, starting with CHAR_MAX + 1. */ -enum -{ - ARGLENGTH_OPTION = CHAR_MAX + 1, /* not quite -l, because of message */ - DEBUGFILE_OPTION, /* no short opt */ - ERROR_OUTPUT_OPTION, /* not quite -o, because of message */ - HASHSIZE_OPTION, /* not quite -H, because of message */ - IMPORT_ENVIRONMENT_OPTION, /* no short opt */ - POPDEF_OPTION, /* no short opt */ - PREPEND_INCLUDE_OPTION, /* not quite -B, because of message */ - SAFER_OPTION, /* -S still has old no-op semantics */ - SYNCOUTPUT_OPTION, /* not quite -s, because of opt arg */ - TRACEOFF_OPTION, /* no short opt */ - WORD_REGEXP_OPTION, /* deprecated, used to be -W */ - - HELP_OPTION, /* no short opt */ - VERSION_OPTION /* no short opt */ -}; - -/* Decode options and launch execution. */ -static const struct option long_options[] = -{ - {"batch", no_argument, NULL, 'b'}, - {"debug", optional_argument, NULL, 'd'}, - {"debuglen", required_argument, NULL, 'l'}, - {"debugmode", optional_argument, NULL, 'd'}, - {"define", required_argument, NULL, 'D'}, - {"discard-comments", no_argument, NULL, 'c'}, - {"fatal-warnings", no_argument, NULL, 'E'}, - {"freeze-state", required_argument, NULL, 'F'}, - {"gnu", no_argument, NULL, 'g'}, - {"include", required_argument, NULL, 'I'}, - {"interactive", no_argument, NULL, 'i'}, - {"nesting-limit", required_argument, NULL, 'L'}, - {"posix", no_argument, NULL, 'G'}, - {"prefix-builtins", no_argument, NULL, 'P'}, - {"pushdef", required_argument, NULL, 'p'}, - {"quiet", no_argument, NULL, 'Q'}, - {"regexp-syntax", optional_argument, NULL, 'r'}, - {"reload-state", required_argument, NULL, 'R'}, - {"silent", no_argument, NULL, 'Q'}, - {"synclines", no_argument, NULL, 's'}, - {"trace", required_argument, NULL, 't'}, - {"traceon", required_argument, NULL, 't'}, - {"traditional", no_argument, NULL, 'G'}, - {"undefine", required_argument, NULL, 'U'}, - {"warnings", no_argument, NULL, 'W'}, - - {"arglength", required_argument, NULL, ARGLENGTH_OPTION}, - {"debugfile", optional_argument, NULL, DEBUGFILE_OPTION}, - {"hashsize", required_argument, NULL, HASHSIZE_OPTION}, - {"error-output", required_argument, NULL, ERROR_OUTPUT_OPTION}, - {"import-environment", no_argument, NULL, IMPORT_ENVIRONMENT_OPTION}, - {"popdef", required_argument, NULL, POPDEF_OPTION}, - {"prepend-include", required_argument, NULL, PREPEND_INCLUDE_OPTION}, - {"safer", no_argument, NULL, SAFER_OPTION}, - {"syncoutput", optional_argument, NULL, SYNCOUTPUT_OPTION}, - {"traceoff", required_argument, NULL, TRACEOFF_OPTION}, - {"word-regexp", required_argument, NULL, WORD_REGEXP_OPTION}, - - {"help", no_argument, NULL, HELP_OPTION}, - {"version", no_argument, NULL, VERSION_OPTION}, - - { NULL, 0, NULL, 0 }, -}; - -/* POSIX requires only -D, -U, and -s; and says that the first two - must be recognized when interspersed with file names. Traditional - behavior also handles -s between files. Starting OPTSTRING with - '-' forces getopt_long to hand back file names as arguments to opt - '\1', rather than reordering the command line. */ -#define OPTSTRING "-B:D:EF:GH:I:L:PQR:S:T:U:Wbcd::egil:o:p:r::st:" - -/* For determining whether to be interactive. */ -enum interactive_choice -{ - INTERACTIVE_UNKNOWN, /* Still processing arguments, no -b or -i yet */ - INTERACTIVE_YES, /* -i specified last */ - INTERACTIVE_NO /* -b specified last */ -}; - -/* Convert OPT to size_t, reporting an error using long option index - OI or short option character OPTCHAR if it does not fit. */ -static size_t -size_opt (char const *opt, int oi, int optchar) -{ - unsigned long int size; - strtol_error status = xstrtoul (opt, NULL, 10, &size, "kKmMgGtTPEZY0"); - if (SIZE_MAX < size && status == LONGINT_OK) - status = LONGINT_OVERFLOW; - if (status != LONGINT_OK) - xstrtol_fatal (status, oi, optchar, long_options, opt); - return size; -} - -/* Process a command line file NAME. */ -static bool -process_file (m4 *context, const char *name) -{ - bool new_input = true; - - if (STREQ (name, "-")) - /* TRANSLATORS: This is a short name for `standard input', used - when a command line file was given as `-'. */ - m4_push_file (context, stdin, _("stdin"), false); - else - new_input = m4_load_filename (context, NULL, name, NULL, false); - - if (new_input) - m4_macro_expand_input (context); - - return new_input; -} - - -/* Main entry point. Parse arguments, load modules, then parse input. */ -int -main (int argc, char *const *argv, char *const *envp) -{ - deferred *head = NULL; /* head of deferred argument list */ - deferred *tail = NULL; - deferred *defn; - size_t size; /* for parsing numeric option arguments */ - - bool import_environment = false; /* true to import environment */ - bool seen_file = false; - const char *debugfile = NULL; - const char *frozen_file_to_read = NULL; - const char *frozen_file_to_write = NULL; - enum interactive_choice interactive = INTERACTIVE_UNKNOWN; - - m4 *context; - - int exit_status; - - /* Initialize gnulib error module. */ - m4_set_program_name (argv[0]); - atexit (close_stdin); - - setlocale (LC_ALL, ""); -#ifdef ENABLE_NLS - textdomain (PACKAGE); -#endif - - context = m4_create (); - -#ifdef USE_STACKOVF - setup_stackovf_trap (argv, envp, stackovf_handler); -#endif - - if (getenv ("POSIXLY_CORRECT")) - { - m4_set_posixly_correct_opt (context, true); - m4_set_suppress_warnings_opt (context, true); - } - set_quoting_style (NULL, escape_quoting_style); - set_char_quoting (NULL, ':', 1); - - /* First, we decode the arguments, to size up tables and stuff. - Avoid lasting side effects; for example 'm4 --debugfile=oops - --help' must not create the file `oops'. */ - while (1) - { - int oi = -1; - int optchar = getopt_long (argc, (char **) argv, OPTSTRING, - long_options, &oi); - if (optchar == -1) - break; - - switch (optchar) - { - default: - usage (EXIT_FAILURE); - - case 'H': - case HASHSIZE_OPTION: - /* -H was supported in 1.4.x, but is a no-op now. FIXME - - remove support for -H after 2.0. */ - error (0, 0, _("warning: `%s' is deprecated"), - optchar == 'H' ? "-H" : "--hashsize"); - break; - - case 'S': - case 'T': - /* Compatibility junk: options that other implementations - support, but which we ignore as no-ops and don't list in - --help. */ - error (0, 0, _("warning: `-%c' is deprecated"), - optchar); - break; - - case WORD_REGEXP_OPTION: - /* Supported in 1.4.x as -W, but no longer present. */ - error (0, 0, _("warning: `%s' is deprecated"), "--word-regexp"); - break; - - case 's': - optchar = SYNCOUTPUT_OPTION; - optarg = "1"; - /* fall through */ - case 'D': - case 'U': - case 'p': - case 'r': - case 't': - case POPDEF_OPTION: - case SYNCOUTPUT_OPTION: - case TRACEOFF_OPTION: - defer: - /* Arguments that cannot be handled until later are accumulated. */ - - defn = (deferred *) xmalloc (sizeof *defn); - defn->code = optchar; - defn->value = optarg; - defn->next = NULL; - - if (head == NULL) - head = defn; - else - tail->next = defn; - tail = defn; - break; - - case '\1': - seen_file = true; - goto defer; - - case 'B': - /* In 1.4.x, -B was a no-op option for compatibility with - Solaris m4. Warn if optarg is all numeric. FIXME - - silence this warning after 2.0. */ - if (isdigit (to_uchar (*optarg))) - { - char *end; - errno = 0; - strtol (optarg, &end, 10); - if (*end == '\0' && errno == 0) - error (0, 0, _("warning: recommend using `-B ./%s' instead"), - optarg); - } - /* fall through */ - case PREPEND_INCLUDE_OPTION: - m4_add_include_directory (context, optarg, true); - break; - - case 'E': - m4_debug_decode (context, "-d", SIZE_MAX); - if (m4_get_fatal_warnings_opt (context)) - m4_set_warnings_exit_opt (context, true); - else - m4_set_fatal_warnings_opt (context, true); - break; - - case 'F': - frozen_file_to_write = optarg; - break; - - case 'G': - m4_set_posixly_correct_opt (context, true); - break; - - case 'I': - m4_add_include_directory (context, optarg, false); - break; - - case 'L': - size = size_opt (optarg, oi, optchar); - if (!size) - size = SIZE_MAX; - m4_set_nesting_limit_opt (context, size); - break; - - case 'P': - m4_set_prefix_builtins_opt (context, true); - break; - - case 'Q': - m4_set_suppress_warnings_opt (context, true); - break; - - case 'R': - frozen_file_to_read = optarg; - break; - - case 'W': - /* FIXME - should W take an optional argument, to allow -Wall, - -Wnone, -Werror, -Wcategory, -Wno-category? If so, then have - -W == -Wall. */ - m4_set_suppress_warnings_opt (context, false); - break; - - case 'b': - interactive = INTERACTIVE_NO; - break; - - case 'c': - m4_set_discard_comments_opt (context, true); - break; - - case 'd': - /* Staggered handling of 'd', since -dm is useful prior to - first file and prior to reloading, but other -d must also - have effect between files. */ - if (seen_file || frozen_file_to_read) - goto defer; - if (m4_debug_decode (context, optarg, SIZE_MAX) < 0) - error (0, 0, _("bad debug flags: %s"), - quotearg_style (locale_quoting_style, optarg)); - break; - - case 'e': - error (0, 0, _("warning: `%s' is deprecated, use `%s' instead"), - "-e", "-i"); - /* fall through */ - case 'i': - interactive = INTERACTIVE_YES; - break; - - case 'g': - m4_set_posixly_correct_opt (context, false); - break; - - case ARGLENGTH_OPTION: - error (0, 0, _("warning: `%s' is deprecated, use `%s' instead"), - "--arglength", "--debuglen"); - /* fall through */ - case 'l': - size = size_opt (optarg, oi, optchar); - if (!size) - size = SIZE_MAX; - m4_set_max_debug_arg_length_opt (context, size); - break; - - case DEBUGFILE_OPTION: - /* Staggered handling of '--debugfile', since it is useful - prior to first file and prior to reloading, but other - uses must also have effect between files. */ - if (seen_file || frozen_file_to_read) - goto defer; - debugfile = optarg; - break; - - case 'o': - case ERROR_OUTPUT_OPTION: - /* FIXME: -o is inconsistent with other tools' use of - -o/--output for creating an output file instead of using - stdout, and --error-output is misnamed since it does not - affect error messages to stderr. Change the meaning of -o - after 2.1. */ - error (0, 0, _("warning: `%s' is deprecated, use `%s' instead"), - optchar == 'o' ? "-o" : "--error-output", "--debugfile"); - /* Don't call m4_debug_set_output here, as it has side effects. */ - debugfile = optarg; - break; - - case IMPORT_ENVIRONMENT_OPTION: - import_environment = true; - break; - - case SAFER_OPTION: - m4_set_safer_opt (context, true); - break; - - case VERSION_OPTION: - version_etc (stdout, PACKAGE, PACKAGE_NAME, VERSION, AUTHORS, NULL); - exit (EXIT_SUCCESS); - break; - - case HELP_OPTION: - usage (EXIT_SUCCESS); - break; - } - } - - /* Do the basic initializations. */ - if (debugfile && !m4_debug_set_output (context, NULL, debugfile)) - m4_error (context, 0, errno, NULL, _("cannot set debug file %s"), - quotearg_style (locale_quoting_style, debugfile)); - m4_input_init (context); - m4_output_init (context); - - if (frozen_file_to_read) - reload_frozen_state (context, frozen_file_to_read); - else - { - m4_module_load (context, "m4", NULL); - if (m4_get_posixly_correct_opt (context)) - m4_module_load (context, "traditional", NULL); - else - m4_module_load (context, "gnu", NULL); - } - - /* Import environment variables as macros. The definition are - prepended to the macro definition list, so -U can override - environment variables. */ - - if (import_environment) - { - char *const *env; - - for (env = envp; *env != NULL; env++) - { - defn = (deferred *) xmalloc (sizeof *defn); - defn->code = 'D'; - defn->value = *env; - defn->next = head; - head = defn; - } - } - - /* Handle deferred command line macro definitions. Must come after - initialization of the symbol table. */ - defn = head; - while (defn != NULL) - { - deferred *next; - const char *arg = defn->value; - - switch (defn->code) - { - case 'D': - case 'p': - { - m4_symbol_value *value = m4_symbol_value_create (); - - const char *str = strchr (arg, '='); - size_t len = str ? str - arg : strlen (arg); - - m4_set_symbol_value_text (value, xstrdup (str ? str + 1 : ""), - str ? strlen (str + 1) : 0, 0); - - if (defn->code == 'D') - m4_symbol_define (M4SYMTAB, arg, len, value); - else - m4_symbol_pushdef (M4SYMTAB, arg, len, value); - } - break; - - case 'U': - m4_symbol_delete (M4SYMTAB, arg, strlen (arg)); - break; - - case 'd': - if (m4_debug_decode (context, arg, SIZE_MAX) < 0) - error (0, 0, _("bad debug flags: %s"), - quotearg_style (locale_quoting_style, arg)); - break; - - case 'r': - m4_set_regexp_syntax_opt (context, m4_regexp_syntax_encode (arg)); - if (m4_get_regexp_syntax_opt (context) < 0) - m4_error (context, EXIT_FAILURE, 0, NULL, - _("bad syntax-spec: %s"), - quotearg_style (locale_quoting_style, arg)); - break; - - case 't': - m4_set_symbol_name_traced (M4SYMTAB, arg, strlen (arg), true); - break; - - case '\1': - if (process_file (context, arg)) - seen_file = true; - break; - - case DEBUGFILE_OPTION: - if (!m4_debug_set_output (context, NULL, arg)) - m4_error (context, 0, errno, NULL, _("cannot set debug file %s"), - quotearg_style (locale_quoting_style, - arg ? arg : _("stderr"))); - break; - - case POPDEF_OPTION: - { - size_t len = strlen (arg); - if (m4_symbol_lookup (M4SYMTAB, arg, len)) - m4_symbol_popdef (M4SYMTAB, arg, len); - } - break; - - case SYNCOUTPUT_OPTION: - { - bool previous = m4_get_syncoutput_opt (context); - m4_call_info info = {0}; - info.name = "--syncoutput"; - info.name_len = strlen (info.name); - m4_set_syncoutput_opt (context, - m4_parse_truth_arg (context, &info, arg, - SIZE_MAX, previous)); - } - break; - - case TRACEOFF_OPTION: - m4_set_symbol_name_traced (M4SYMTAB, arg, strlen (arg), false); - break; - - default: - assert (!"INTERNAL ERROR: bad code in deferred arguments"); - abort (); - } - - next = defn->next; - free (defn); - defn = next; - } - - - /* Interactive if specified, or if no input files and stdin and - stderr are terminals, to match sh behavior. Interactive mode - means unbuffered output, and interrupts ignored. */ - - m4_set_interactive_opt (context, (interactive == INTERACTIVE_YES - || (interactive == INTERACTIVE_UNKNOWN - && optind == argc && !seen_file - && isatty (STDIN_FILENO) - && isatty (STDERR_FILENO)))); - if (m4_get_interactive_opt (context)) - { - signal (SIGINT, SIG_IGN); - setbuf (stdout, NULL); - } - else - signal (SIGPIPE, SIG_DFL); - - - /* Handle remaining input files. Each file is pushed on the input, - and the input read. */ - - if (optind == argc && !seen_file) - process_file (context, "-"); - else - for (; optind < argc; optind++) - process_file (context, argv[optind]); - - /* Now handle wrapup text. - FIXME - when -F is in effect, should wrapped text be frozen? */ - while (m4_pop_wrapup (context)) - m4_macro_expand_input (context); - - if (frozen_file_to_write) - produce_frozen_state (context, frozen_file_to_write); - else - { - m4_make_diversion (context, 0); - m4_undivert_all (context); - } - - /* The remaining cleanup functions systematically free all of the - memory we still have pointers to. By definition, if there is - anything left when we're done: it was caused by a memory leak. - Strictly, we don't need to do this, but it makes leak detection - a whole lot easier! */ - - m4_output_exit (); - m4_input_exit (); - - /* Change debug stream back to stderr, to force flushing the debug - stream and detect any errors it might have encountered. The - three standard streams are closed by close_stdin. */ - m4_debug_set_output (context, NULL, NULL); - - exit_status = m4_get_exit_status (context); - m4_delete (context); - - m4_hash_exit (); - quotearg_free (); - -#ifdef USE_STACKOVF - stackovf_exit (); -#endif - - exit (exit_status); -} diff --git a/src/stackovf.c b/src/stackovf.c deleted file mode 100644 index 3d0468ab..00000000 --- a/src/stackovf.c +++ /dev/null @@ -1,454 +0,0 @@ -/* Detect stack overflow (when getrlimit and sigaction or sigvec are available) - Copyright (C) 1993-1994, 2006-2007, 2010, 2013-2014, 2017 Free - Software Foundation, Inc. - Jim Avera , 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 . - */ - -/* 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 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 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 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 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." */ - -/* Define this to see runtime debug info. Implied by DEBUG. */ -/*#define DEBUG_STKOVF */ - -#include - -#include "m4.h" - -#ifdef USE_STACKOVF - -#include -#include - -#if HAVE_SIGINFO_H -# include -#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); - -#if defined __ultrix && defined __vax -extern char *sbrk (int); -extern int getrlimit (int, struct rlimit *); -extern int sigstack (struct sigstack *, struct sigstack *); -extern int sigvec (int, struct sigvec *, struct sigvec *); -#endif - -static void *stackbuf; -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) -{ - ptrdiff_t diff; - diff = (p - stackend); - -#ifdef DEBUG_STKOVF - { - char buf[200]; - - sprintf (buf, - "process_sigsegv: p=%p stackend=%p diff=%" PRIdPTR "bot=%p\n", - p, stackend, diff, stackbot); - write (2, buf, strlen (buf)); - } -#endif - - if (p != PARAM_NOSTACKOVF) - { - if ((long) sbrk (8192) == (long) -1) - { - const char *cp; - - /* sbrk failed. Assume the RLIMIT_VMEM prevents expansion even - if the stack limit has not been reached. */ - - /* FIXME - calling gettext inside a signal handler is - dangerous, since it can call malloc, which is not signal - safe. We can sort of justify it by the fact that this - handler is designed to exit() the program, but it could - really use a better fix. */ - cp = _("VMEM limit exceeded?\n"); - write (2, cp, strlen (cp)); - 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; - - /* FIXME - calling gettext inside a signal handler is dangerous, - since it can call malloc, which is not signal safe. */ - 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 cannot 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 /* ! HAVE_STACK_T_SS_SP */ - - stackbuf = xmalloc (SIGSTKSZ); - - ss.ss_size = SIGSTKSZ; - ss.ss_sp = stackbuf; - ss.ss_flags = 0; - if (sigaltstack (&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, _("sigaltstack")); - } - } - -#elif HAVE_SIGSTACK - - { - struct sigstack ss; - 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 */ - -} - -void -stackovf_exit (void) -{ - DELETE (stackbuf); -} - -#endif /* USE_STACKOVF */ diff --git a/tests/atlocal.in b/tests/atlocal.in deleted file mode 100644 index dd6f35ee..00000000 --- a/tests/atlocal.in +++ /dev/null @@ -1,27 +0,0 @@ -# -*- shell-script -*- -# @configure_input@ -# Configurable variable values for M4 test suite. -# Copyright (C) 2000-2001, 2006, 2008, 2010, 2013-2014, 2017 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 . - -# Some tests cannot be performed with all the configurations. -USE_GMP=@USE_GMP@ - -# Prefer tools learned during configure. -SED='@SED@' -export SED diff --git a/tests/builtins.at b/tests/builtins.at deleted file mode 100644 index ab8fa9f6..00000000 --- a/tests/builtins.at +++ /dev/null @@ -1,1325 +0,0 @@ -# Hand crafted tests for GNU M4. -*- Autotest -*- -# Copyright (C) 2001, 2006-2010, 2013-2014, 2017 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 . - -AT_BANNER([Torturing builtins.]) - - -## -------- ## -## __file__ ## -## -------- ## - -AT_SETUP([__@&t@file__]) - -dnl Unfortunately, AT_DATA does not make it easy to create files without -dnl a trailing newline. -[echo $ECHO_N "__line"__:__"file__$ECHO_C"] > nested -AT_DATA([outer], -[[__file__:__line__ -include(`nested') -__file__:__line__ -]]) - -dnl Make sure line numbers are consistent, even if include file does not -dnl end with a newline -AT_CHECK_M4([outer], [0], -[[outer:1 -1:nested -outer:3 -]]) - -AT_CLEANUP - - -## -------- ## -## __line__ ## -## -------- ## - -AT_SETUP([__@&t@line__]) - -dnl Unfortunately, AT_DATA does not make it easy to create files without -dnl a trailing newline. -[echo $ECHO_N "__file"__:__"line__$ECHO_C"] > nested -AT_DATA([outer], -[[__file__:__line__ -include(`nested') -__file__:__line__ -]]) - -dnl Make sure line numbers are consistent, even if include file does not -dnl end with a newline -AT_CHECK_M4([outer], [0], -[[outer:1 -nested:1 -outer:3 -]]) - -AT_CLEANUP - - -## -------------- ## -## __m4_version__ ## -## -------------- ## - -AT_SETUP([__m4_@&t@version__]) - -AT_DATA([in], [[defn(`__m4_version__') -]]) -AT_CHECK_M4([--version], [0], [stdout]) -AT_CHECK([[$SED -e 's/.*(GNU M4\(.*\)) \([^ ]*\).*/\2\1/;q' < stdout]], -[0], [stdout]) -mv stdout expout -AT_CHECK_M4([in], [0], [expout]) - -dnl Prove that __m4_version__ is unquoted, by making '.' an active character. -AT_DATA([in], [[changesyntax(`A.')define(`.', `errprint(`hi -')undefine(`.').')dnl -__m4_version__ -]]) -AT_CHECK_M4([in], [0], [expout], [[hi -]]) - -AT_CLEANUP - - -## ------- ## -## builtin ## -## ------- ## - -AT_SETUP([builtin]) - -dnl This was a regression in 1.4.10b. -AT_DATA([in.m4], -[[define(`s', `builtin(`shift', $@)')dnl -define(`loop', `ifelse(`$2', `', `-', `$1$2: $0(`$1', s(s($@)))')')dnl -loop(`1') -loop(`1', `2') -loop(`1', `2', `3') -loop(`1', `2', `3', `4') -loop(`1', `2', `3', `4', `5') -]]) -AT_CHECK_M4([in.m4], [0], -[[- -12: - -12: 13: - -12: 13: 14: - -12: 13: 14: 15: - -]]) - -AT_CLEANUP - - -## ----------- ## -## changequote ## -## ----------- ## - -AT_SETUP([changequote]) - -AT_DATA([in.m4], -[[define(`aaaaaaaaaaaaaaaaaaaa', `A')define(`q', `"$@"') -changequote(`"', `"') -q(q("aaaaaaaaaaaaaaaaaaaa", "a")) -changequote`'define(`echo', `$@')dnl -changequote(`<<<', `>>')dnl -echo(<<>>>) -]]) - -AT_CHECK_M4([in.m4], [0], [[ - -A,a -a<<> -]]) - -AT_CLEANUP - - -## ----- ## -## debug ## -## ----- ## - -AT_SETUP([debug]) - -AT_DATA([[debug.m4]], -[[define(`countdown', `$1 ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Liftoff')') -debugmode(`aeqc') -traceon(`countdown') -countdown(2) -]]) - -AT_DATA([[expout]], -[[ - - -2 1 0 Liftoff -]]) - -AT_DATA([[experr]], -[[m4trace: -1- countdown ... = `$1 ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Liftoff')' -m4trace: -1- countdown(`2') -> `2 ifelse(eval(2 > 0), 1, `countdown(decr(2))', `Liftoff')' -m4trace: -1- countdown ... = `$1 ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Liftoff')' -m4trace: -1- countdown(`1') -> `1 ifelse(eval(1 > 0), 1, `countdown(decr(1))', `Liftoff')' -m4trace: -1- countdown ... = `$1 ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Liftoff')' -m4trace: -1- countdown(`0') -> `0 ifelse(eval(0 > 0), 1, `countdown(decr(0))', `Liftoff')' -]]) - -AT_CHECK_M4([debug.m4], 0, expout, experr) - -dnl Test a regression introduced 2008-05-08, fixed 2008-07-30. -AT_DATA([debug.m4], [[debugmode(`e')traceon(`ifelse')dnl -define(`e', `ifelse(`$1', `$2', `ifelse(`$1', `$2', `e(shift($@))')', `$2')') -e(`1', `1', `a') -]]) - -AT_CHECK_M4([debug.m4], [0], [[ -a -]], [[m4trace: -1- ifelse -> ifelse(`1', `1', `e(shift(`1',`1',`a'))') -m4trace: -1- ifelse -> e(shift(`1',`1',`a')) -m4trace: -1- ifelse -> a -]]) - -AT_CLEANUP - - -## ------ ## -## define ## -## ------ ## - -AT_SETUP([define]) - -AT_DATA([[define.m4]], -[[undefine(`macro')dnl -pushdef(`macro', `base value')dnl -pushdef(`macro', `hello, world')dnl -pushdef(`macro', `top value')dnl -define(`macro', `new value')dnl -macro. -popdef(`macro')dnl -macro. -popdef(`macro')dnl -macro. -]]) - -AT_CHECK_M4([define.m4], 0, -[[new value. -hello, world. -base value. -]], [[m4:define.m4:1: warning: undefine: undefined macro 'macro' -]]) - -AT_CHECK_M4([--traditional define.m4], 0, -[[new value. -hello, world. -base value. -]], [[m4:define.m4:1: warning: undefine: undefined macro 'macro' -]]) - -dnl check regression present 2008-02-22 to 2008-04-30. -AT_DATA([in.m4], [[define(`qq', ``$*;$@'')dnl -define(`foo', qq(`a', `b'))dnl -foo -defn(`foo') -]]) -AT_CHECK_M4([in.m4], [0], [[a,b;a,b -a,b;`a',`b' -]]) - -dnl Check hashing performance. -AT_DATA([in.m4], [[include(`forloop3.m4')dnl -forloop(`i', `1', `10000', `define(`m'i, i)')m10000 -forloop(`i', `1', `10000', `undefine(`m'i)')m10000 -]]) -AT_CHECK_M4([-I "$abs_top_srcdir/doc/examples" in.m4], [0], [[10000 -m10000 -]]) - -AT_CLEANUP - - - -## ---- ## -## defn ## -## ---- ## - -AT_SETUP([defn]) - -AT_DATA([[in.m4]], -[[define(`e', `$@')define(`q', ``$@'')define(`u', `$*') -define(`cmp', `ifelse($1, $2, `yes', `no')')define(`d', defn(`defn')) -cmp(`defn(`defn')', `defn(`d')') -cmp(`defn(`defn')', ``'') -cmp(`q(defn(`defn'))', `q(defn(`d'))') -cmp(`q(defn(`defn'))', `q(`')') -cmp(`q(defn(`defn'))', ``'') -cmp(`q(`1', `2', defn(`defn'))', `q(`1', `2', defn(`d'))') -cmp(`q(`1', `2', defn(`defn'))', `q(`1', `2', `')') -cmp(`q(`1', `2', defn(`defn'))', ```1',`2','') -cmp(`q(`1', `2', defn(`defn'))', ```1',`2',`''') -define(`cat', `$1`'ifelse(`$@%:@', `1', `', `$0(shift($@))')') -cat(`define(`foo',', defn(`divnum'), `)foo') -cat(e(`define(`bar',', defn(`divnum'), `)bar')) -m4wrap(`u('q(`cat(`define(`baz','', defn(`divnum'), ``)baz')')`) -') -]]) - -AT_CHECK_M4([in.m4], [0], [[ - -yes -no -yes -no -no -yes -no -no -no - -0 -0 - -0 -]]) - -AT_CLEANUP - - -## ------ ## -## divert ## -## ------ ## - -AT_SETUP([divert]) - -AT_DATA([[divert.m4]], -[[divert(1)Text diverted a first time. -divert(0)undivert(1)dnl -divert(1)Text diverted a second time. -divert(0)undivert(1)dnl -]]) - -AT_CHECK_M4([divert.m4], 0, -[[Text diverted a first time. -Text diverted a second time. -]]) - -dnl Test second divert argument, added for m4 2.0 -AT_DATA([in.m4], [[define(`echo',`$1')dnl -divert(`-1', `discarded without warning') -divert`'dnl -echo(` world'divert(divnum, `hello')) -]]) - -AT_CHECK_M4([-s in.m4], [0], [[#line 4 "in.m4" -hello world -]]) - -dnl Test large diversions, which were broken in m4 1.4.8-1.4.10. -dnl Hopefully $SED doesn't choke on the over-long second line. -AT_CHECK([echo 'divert(1)hi -format(%1000000d, 1)' | $M4 | $SED -n 1p], [0], [[hi -]]) - -AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(`2')f`'dnl -divert(`1')hello -divert(`3')goodbye -]]) - -dnl Rather than open-code the 1 megabyte expected output, we reduce the -dnl size of testsuite by constructing it. -AT_DATA([expout], [[ -]]) -cat expout expout > expout2 -cat expout2 expout2 > expout -cat expout expout > expout2 -cat expout2 expout2 > expout -cat expout expout > expout2 -cat expout2 expout2 > expout -cat expout expout > expout2 -cat expout2 expout2 > expout -cat expout expout > expout2 -cat expout2 expout2 > expout -cat expout expout > expout2 -cat expout2 expout2 > expout -cat expout expout > expout2 -cat expout2 expout2 > expout -cat expout expout > expout2 -cat expout2 expout2 > expout -cat expout expout > expout2 -cat expout2 expout2 > expout -cat expout expout > expout2 # 512 kilobytes -echo hello > expout -cat expout2 expout2 >> expout # 1 megabyte -echo goodbye >> expout -rm expout2 - -AT_CHECK_M4([in.m4], [0], [expout]) - -dnl Avoid quadratic copying time when transferring diversions; test -dnl both in-memory and diversions spilled to a file. -AT_DATA([in.m4], [[include(`forloop2.m4')dnl -divert(`1')format(`%10000s', `')dnl -forloop(`i', `1', `10000', - `divert(incr(i))undivert(i)')dnl -divert(`9001')format(`%1000000s', `')dnl -forloop(`i', `9001', `10000', - `divert(incr(i))undivert(i)')dnl -divert(`-1')undivert -]]) - -AT_CHECK_M4([-I "$abs_top_srcdir/doc/examples" in.m4]) - -AT_CLEANUP - - -## --- ## -## dnl ## -## --- ## - -AT_SETUP([d@&t@nl]) - -dnl Unfortunately, AT_DATA does not make it easy to create files without -dnl a trailing newline. -[echo $ECHO_N "__file"__:__"line__ d""nl ignored$ECHO_C"] > nested -AT_DATA([outer], -[[__file__:__line__ -include(`nested') still ignored -__file__:__line__ -define(`foo', `dnl -__file__:__line__ include(`nested') ignored -dnl')dnl -foo ignored -__file__:__line__ -]]) - -dnl Make sure line numbers are consistent, even if include file does not -dnl end with a newline -AT_CHECK_M4([outer], [0], -[[outer:1 -nested:1 outer:3 -outer:7 nested:1 outer:8 -]]) - -AT_CLEANUP - - -## ------- ## -## dumpdef ## -## ------- ## - -AT_SETUP([dumpdef]) - -dnl Make sure that stderr and stdout are properly interleaved when directed -dnl to the same file. -AT_DATA([in], [[1dumpdef(`defn')3 -]]) -AT_CHECK_M4([in], [0], [[13 -]], [[defn: -]]) -AT_CHECK_M4([in 2>&1], [0], [[1defn: -3 -]]) - -AT_CLEANUP - - -## -------- ## -## errprint ## -## -------- ## - -AT_SETUP([errprint]) - -dnl Make sure that stderr and stdout are properly interleaved when directed -dnl to the same file. -AT_DATA([in], [[1errprint(`2')3errprint(` -') -]]) -AT_CHECK_M4([in], [0], [[13 -]], [[2 -]]) -AT_CHECK_M4([in 2>&1], [0], [[123 - -]]) - -AT_CLEANUP - - -## ------- ## -## esyscmd ## -## ------- ## - -AT_SETUP([esyscmd]) - -AT_DATA([[esyscmd.m4]], -[[# Cannot use real hostname program because test would fail -define(`hostname', esyscmd(`echo www.gnu.org'))dnl -`hostname = >>'hostname`<<' -define(`hostname', -pushdef(`_tmp', `$1')_tmp(translit(esyscmd(`echo www.gnu.org'), `.', `,'))`'popdef(`_tmp'))dnl -`hostname = >>'hostname`<<' -]]) - -AT_CHECK_M4([esyscmd.m4], 0, -[[# Cannot use real hostname program because test would fail -hostname = >>www.gnu.org -<< -hostname = >>www<< -]]) - -dnl Ensure that esyscmd does not inherit any unnecessary fds from trace. -AT_DATA([in.m4], [[esyscmd(`echo hi >&3')ifelse(sysval, -`0', `skipping: sh cannot detect closed fds -m4exit(`77')')dnl -]]) -AT_CHECK_M4([3>&-], [0], [], [stderr], [in.m4]) -mv stderr experr -AT_CHECK_M4([--debugfile=trace -tdnl 3>&-], [0], [], [experr], [in.m4]) -AT_CHECK([cat trace], [0], [[m4trace: -1- dnl -> `' -]]) - -dnl Ensure that esyscmd does not inherit any unnecessary fds from diversions. -AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(`1')f -world -esyscmd(`echo hi >&3')divert -hello -]]) -AT_CHECK_M4([3>&-], [0], [stdout-nolog], [experr], [in.m4]) -AT_CHECK([$SED -ne '/./p' stdout], [0], [[hello -world -]]) - -dnl Ensure that esyscmd does not inherit any unnecessary fds from input files. -AT_DATA([in.m4], [[hello esyscmd(`cat <&3')dnl -dnl this line should not be read by cat -world -]]) -AT_CHECK_M4([3>&-], [0], [[hello world -]], [stderr], [in.m4]) -mv stderr experr -AT_CHECK_M4([in.m4 3>&-], [0], [[hello world -]], [experr]) - -AT_CLEANUP - - -## ------ ## -## ifelse ## -## ------ ## - -AT_TEST_M4([ifelse], -dnl ensure that comparisons work regardless of reference chains in the middle -[[define(`e', `$@')define(`long', `01234567890123456789') -dnl in isolation -ifelse(long, `01234567890123456789', `yes', `no') -ifelse(`01234567890123456789', long, `yes', `no') -ifelse(long, `01234567890123456789-', `yes', `no') -ifelse(`01234567890123456789-', long, `yes', `no') -dnl through macro expansion -ifelse(e(long), `01234567890123456789', `yes', `no') -ifelse(`01234567890123456789', e(long), `yes', `no') -ifelse(e(long), `01234567890123456789-', `yes', `no') -ifelse(`01234567890123456789-', e(long), `yes', `no') -dnl concatenate macro expansion with unquoted characters -ifelse(-e(long), `-01234567890123456789', `yes', `no') -ifelse(-`01234567890123456789', -e(long), `yes', `no') -ifelse(-e(long), `-01234567890123456789-', `yes', `no') -ifelse(`-01234567890123456789-', -e(long), `yes', `no') -ifelse(-e(long)-, `-01234567890123456789-', `yes', `no') -ifelse(-`01234567890123456789-', -e(long)-, `yes', `no') -ifelse(-e(long)-, `-01234567890123456789', `yes', `no') -ifelse(`-01234567890123456789', -e(long)-, `yes', `no') -dnl concatenate macro expansion with quoted characters -ifelse(`-'e(long), `-01234567890123456789', `yes', `no') -ifelse(-`01234567890123456789', `-'e(long), `yes', `no') -ifelse(`-'e(long), `-01234567890123456789-', `yes', `no') -ifelse(`-01234567890123456789-', `-'e(long), `yes', `no') -ifelse(`-'e(long)`-', `-01234567890123456789-', `yes', `no') -ifelse(-`01234567890123456789-', `-'e(long)`-', `yes', `no') -ifelse(`-'e(long)`-', `-01234567890123456789', `yes', `no') -ifelse(`-01234567890123456789', `-'e(long)`-', `yes', `no') -]], [[ -yes -yes -no -no -yes -yes -no -no -yes -yes -no -no -yes -yes -no -no -yes -yes -no -no -yes -yes -no -no -]]) - - -## ------- ## -## include ## -## ------- ## - -AT_SETUP([include]) - -AT_DATA([[include.m4]], -[[Beginning. -include(`NOFILE') -Intermediate -include(`incl-test.m4') -After -include(`NOFILE') -very late -]]) - -AT_DATA([[incl-test.m4]], -[[dnl noauto -`include test file.' -define() -]]) - -AT_DATA([[expout]], -[[Beginning. - -Intermediate -include test file. - - -After - -very late -]]) - -AT_DATA([[experr]], -[[m4:include.m4:2: include: cannot open file 'NOFILE': No such file or directory -m4:include.m4:6: include: cannot open file 'NOFILE': No such file or directory -]]) - -AT_CHECK_M4([include.m4], 1, expout, experr) - -dnl make sure files are handled correctly even via builtin -AT_DATA([foo], [[bar -]]) -AT_DATA([in], [[builtin(`include', `foo')dnl -]]) - -AT_CHECK_M4([in], [0], [[bar -]]) - -AT_CLEANUP - - - -## ----- ## -## index ## -## ----- ## - -AT_SETUP([index]) - -dnl This used to be quadratic, taking millions of comparisons, -dnl but should now operate in linear time with only several thousand checks. -AT_DATA([in], [M4_ONE_MEG_DEFN[dnl -index(substr(f, `0', `500000')-, substr(f, `0', `100000')-) -]]) -AT_CHECK_M4([in], [0], [[400000 -]]) - -dnl This validates that index is 8-bit safe. -AT_DATA([in], [[index(`1«2', `»') -index(`1«2', `«') -index(`1«2', `«1') -index(`1«2', `«2') -]]) -AT_CHECK_M4([in], [0], [[-1 -1 --1 -1 -]]) - -AT_CLEANUP - - - -## ----- ## -## indir ## -## ----- ## - -AT_SETUP([indir]) - -AT_DATA([[indir.m4]], -[[define(`%%$$##', `>>>$0<<< cnt $#') - -# indir(`%%$$##', nonsense, nonsense) -indir(`%%$$##', nonsense, nonsense) - -# indir(`indir', `%%$$##', nonsense) -indir(`indir', `%%$$##', nonsense) - -# indir(`indir', `indir', `indir', `indir', `%%$$##') -indir(`indir', `indir', `indir', `indir', `%%$$##') -]]) - -AT_DATA([[expout]], -[[ - -# indir(`%%$$##', nonsense, nonsense) ->>>%%$$##<<< cnt 2 - -# indir(`indir', `%%$$##', nonsense) ->>>%%$$##<<< cnt 1 - -# indir(`indir', `indir', `indir', `indir', `%%$$##') ->>>%%$$##<<< cnt 0 -]]) - -AT_CHECK_M4([indir.m4], 0, expout) - -AT_CLEANUP - - -## ------ ## -## m4exit ## -## ------ ## - -AT_SETUP([m4exit]) - -dnl Ensure that spilled diversions are gracefully cleaned up -AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(`1')f -m4exit -]]) -AT_CHECK([rm -Rf tmpdir && mkdir tmpdir && test -d tmpdir]) -TMPDIR=tmpdir -export TMPDIR -AT_CHECK_M4([in.m4], [0]) -AT_CHECK([rmdir tmpdir]) - -AT_CLEANUP - - -## ------- ## -## mkdtemp ## -## ------- ## - -AT_SETUP([mkdtemp]) - -dnl Check that on error, the expansion is void -AT_DATA([[in]], -[[mkdtemp(`no_such_dir/m4-fooXXXXXX') -]]) -AT_CHECK_M4([in], [0], [[ -]], [[m4:in:1: warning: mkdtemp: cannot create directory from template 'no_such_dir/m4-fooXXXXXX': No such file or directory -]]) - -dnl Check that umask has an effect. drws--S--T is okay. -AT_DATA([[in]], -[[translit(substr(esyscmd(`ls -ld 'mkdtemp(`m4-fooXXXXXX')), `0', `10'), - `SsT', `-x-') -]]) -AT_CHECK([$M4 < in], [0], [[drwx------ -]]) -AT_CHECK([umask 700; $M4 < in], [0], [[d--------- -]]) - -AT_CLEANUP - - -## -------- ## -## maketemp ## -## -------- ## - -AT_SETUP([mkstemp]) - -AT_KEYWORDS([maketemp]) - -dnl Check that on error, the expansion is void -AT_DATA([[in]], -[[mkstemp(`no_such_dir/m4-fooXXXXXX') -]]) -AT_CHECK_M4([in], [0], [[ -]], [[m4:in:1: warning: mkstemp: cannot create file from template 'no_such_dir/m4-fooXXXXXX': No such file or directory -]]) - -dnl Check that extra X are appended, but not trailing NUL -AT_DATA([[in]], [[len(mkstemp(`m4-fooXXXXX')) -]]) -AT_CHECK_M4([in], [0], [[12 -]]) - -dnl Check that umask has an effect -AT_DATA([[in]], -[[substr(esyscmd(`ls -ld 'mkstemp(`m4-fooXXXXXX')), `0', `10') -]]) -AT_CHECK([$M4 < in], [0], [[-rw------- -]]) -AT_CHECK([umask 700; $M4 < in], [0], [[---------- -]]) - -dnl Check for Solaris compatibility of maketemp. Hopefully the pid is -dnl less than 20 decimal digits. Also check that --safer does not affect -dnl traditional behavior of maketemp, which is textual only. -AT_DATA([[in]], -[[maketemp() -maketemp(X) -maketemp(XX) -maketemp(XXXXXXXXXXXXXXXXXXXXX) -maketemp(no_such_dir/XXXXXX) -]]) -dnl Abuse our knowledge of AT_CHECK_M4 so that we can get stderr filtering... -AT_CHECK_M4([-G -Q --safer], [0], [stdout], [], -[in& echo $! > pid; wait $!]) -pid=`cat pid` -cat >expout <*>*>*>*>!, !<*<*<*<**>*>*>*>foo bar<*<*<*<*< -foo bar ->*>*>*>*>*>*><*<*<*<*<*<*< -dumpdef(>*>*>*>*>foo<*<*<*<*<, >*>*>*>*>bar<*<*<*<*<)dnl -]]) - -AT_DATA([[expout]], -[[ -``traceon'' -foo -``FOO'' - -BAR -foo bar -``FOO'' BAR -*>*>*<*< -]]) - -AT_DATA([[experr]], -[[m4trace: -1- changequote(`[', `]') -> [] -m4trace: -1- dnl -> [] -m4trace: -1- changequote([``], ['']) -> ``'' -m4trace: -1- dnl -> ``'' -m4trace: -1- define(``foo'', ````FOO'''') -> ``'' -m4trace: -1- dnl -> ``'' -foo: ````FOO'''' -m4trace: -1- dumpdef(``foo'') -> ``'' -m4trace: -1- dnl -> ``'' -m4trace: -1- changequote(``!'', ``!'') -> !! -m4trace: -1- dnl -> !! -m4trace: -1- foo -> !``FOO''! -foo: !``FOO''! -m4trace: -1- dumpdef(!foo!) -> !! -m4trace: -1- dnl -> !! -m4trace: -1- define(!bar!, !BAR!) -> !! -m4trace: -1- bar -> !BAR! -m4trace: -1- changequote(!>*>*>*>*>!, !<*<*<*<* >*>*>*>*><*<*<*<*< -m4trace: -1- dnl -> >*>*>*>*><*<*<*<*< -m4trace: -1- foo -> >*>*>*>*>``FOO''<*<*<*<*< -m4trace: -1- bar -> >*>*>*>*>BAR<*<*<*<*< -bar: >*>*>*>*>BAR<*<*<*<*< -foo: >*>*>*>*>``FOO''<*<*<*<*< -m4trace: -1- dumpdef(>*>*>*>*>foo<*<*<*<*<, >*>*>*>*>bar<*<*<*<*<) -> >*>*>*>*><*<*<*<*< -m4trace: -1- dnl -> >*>*>*>*><*<*<*<*< -]]) - -AT_CHECK_M4([multiquotes.m4], 0, expout, experr) - -AT_CLEANUP - - - -## -------- ## -## patsubst ## -## -------- ## - -AT_SETUP([patsubst]) - -AT_DATA([[patsubst.m4]], -[[# traceon(`patsubst') -patsubst(`GNUs not Unix.', `^', `OBS: ') -patsubst(`GNUs not Unix.', `\<', `OBS: ') -patsubst(`GNUs not Unix.', `\<\w', `\&=') -patsubst(`GNUs not Unix.', `\w*', `(\&)') -patsubst(`GNUs not Unix.', `\w+', `(\&)') -patsubst(`GNUs not Unix.', `\w+') -patsubst(`GNUs not '` Unix.', `[ ]+', ` ') -]]) - -AT_DATA([[expout]], -[[# traceon(`patsubst') -OBS: GNUs not Unix. -OBS: GNUs OBS: not OBS: Unix. -G=NUs n=ot U=nix. -(GNUs)() (not)() (Unix)().() -(GNUs) (not) (Unix). - . -GNUs not Unix. -]]) - -AT_CHECK_M4([patsubst.m4], 0, expout) - -AT_CLEANUP - - - -## ------ ## -## regexp ## -## ------ ## - -AT_SETUP([regexp]) - -AT_DATA([[regexp.m4]], -[[traceon(`regexp')dnl -regexp(`hej med dig', `.*', `>>\&<<') -regexp(`hej med dig', `\w*', `>>\&<<') -regexp(`hej med dig', `.+', `>>\&<<') -regexp(`hej med dig', `m\w+', `>>\&<<') -regexp(`hej med dig', `m\(.*\)', `>>\&<< >>\1<<') - -regexp(`hej med dig', `.*') -regexp(`hej med dig', `\w*') -regexp(`hej med dig', `.+') -regexp(`hej med dig', `m\w+') -regexp(`hej med dig', `m\(.*\)') -]]) - -AT_DATA([[expout]], -[[>>hej med dig<< ->>hej<< ->>hej med dig<< ->>med<< ->>med dig<< >>ed dig<< - -0 -0 -0 -4 -4 -]]) - -AT_DATA([[experr]], -[[m4trace: -1- regexp(`hej med dig', `.*', `>>\&<<') -> `>>hej med dig<<' -m4trace: -1- regexp(`hej med dig', `\w*', `>>\&<<') -> `>>hej<<' -m4trace: -1- regexp(`hej med dig', `.+', `>>\&<<') -> `>>hej med dig<<' -m4trace: -1- regexp(`hej med dig', `m\w+', `>>\&<<') -> `>>med<<' -m4trace: -1- regexp(`hej med dig', `m\(.*\)', `>>\&<< >>\1<<') -> `>>med dig<< >>ed dig<<' -m4trace: -1- regexp(`hej med dig', `.*') -> `0' -m4trace: -1- regexp(`hej med dig', `\w*') -> `0' -m4trace: -1- regexp(`hej med dig', `.+') -> `0' -m4trace: -1- regexp(`hej med dig', `m\w+') -> `4' -m4trace: -1- regexp(`hej med dig', `m\(.*\)') -> `4' -]]) - -AT_CHECK_M4([regexp.m4], 0, expout, experr) - -AT_CLEANUP - - - -## ------------ ## -## sync-lines. ## -## ------------ ## - -AT_SETUP([sync-lines]) - -AT_DATA([[in]], -[[syncoutput(on)dnl -# Several input lines, expanding to one -define(`foo', ``foo' line one. -`foo' line two. -`foo' line three.') xyz -foo -# Several input lines, expanding to none -define(`foo', ``foo' line one. -`foo' line two. -`foo' line three.')dnl -# one input line, expanding to several output lines -foo foo -]]) - -AT_CHECK_M4([[in]], 0, -[[#line 2 "in" -# Several input lines, expanding to one -#line 5 - xyz -foo line one. -#line 6 -foo line two. -#line 6 -foo line three. -# Several input lines, expanding to none -#line 11 -# one input line, expanding to several output lines -foo line one. -#line 12 -foo line two. -#line 12 -foo line three. foo line one. -#line 12 -foo line two. -#line 12 -foo line three. -]]) - -AT_CLEANUP - - -## ------ ## -## syscmd ## -## ------ ## - -AT_SETUP([syscmd]) - -dnl Ensure that syscmd does not inherit any unnecessary fds from trace. -AT_DATA([in.m4], [[syscmd(`echo hi >&3')ifelse(sysval, -`0', `skipping: sh cannot detect closed fds -m4exit(`77')')dnl -]]) -AT_CHECK_M4([3>&-], [0], [], [stderr], [in.m4]) -mv stderr experr -AT_CHECK_M4([--debugfile=trace -tdnl 3>&-], [0], [], [experr], [in.m4]) -AT_CHECK([cat trace], [0], [[m4trace: -1- dnl -> `' -]]) - -dnl Ensure that syscmd does not inherit any unnecessary fds from diversions. -AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(`1')f -world -syscmd(`echo hi >&3')divert -hello -]]) -AT_CHECK_M4([3>&-], [0], [stdout-nolog], [experr], [in.m4]) -AT_CHECK([$SED -ne '/./p' stdout], [0], [[hello -world -]]) - -dnl Ensure that syscmd does not inherit any unnecessary fds from input files. -AT_DATA([in.m4], [[hello syscmd(`cat <&3')dnl -dnl this line should not be read by cat -world -]]) -AT_CHECK_M4([3>&-], [0], [[hello world -]], [stderr], [in.m4]) -mv stderr experr -AT_CHECK_M4([in.m4 3>&-], [0], [[hello world -]], [experr]) - -AT_CLEANUP - - -## -------- ## -## translit ## -## -------- ## - -AT_SETUP([translit]) - -AT_DATA([[translit.m4]], -[[# traceon(`translit')dnl -translit(`GNUs not Unix', `a-z') -translit(`GNUs not Unix', `a-z', `A-Z') -translit(`GNUs not Unix', `A-Z', `a-z') -translit(`GNUs not Unix', `A-Z') -translit(`a-z', `a-') -translit(`A-Z', `A-Z-', `-A-Z') -translit(`GNUs not Unix', `Z-A', `a-z') -]]) - -AT_CHECK_M4([translit.m4], 0, -[[# traceon(`translit')dnl -GNU U -GNUS NOT UNIX -gnus not unix -s not nix -z --ZY -tmfs not fnix -]]) - -dnl This used to be quadratic, taking millions of comparisons, -dnl but should now operate in linear time with only several thousand checks. -AT_DATA([in], [M4_ONE_MEG_DEFN[dnl -define(`a_', translit(substr(f, `0', `50000'), ` -', `a'))dnl -define(`b_', translit(substr(f, `0', `50000'), ` -', `b'))dnl -define(`d_', translit(substr(f, `0', `50000'), ` -', `d'))dnl -define(`c'd_, `pass')dnl -translit(`a'b_, a_`b', `c'd_) -]]) -AT_CHECK_M4([in], [0], [[pass -]]) - -dnl This validates that ranges are built using unsigned chars. -AT_DATA([in], [[translit(`«abc~', `~-»') -]]) -AT_CHECK_M4([in], [0], [[abc -]]) - -dnl Validate short strings, which take a different code path. -AT_DATA([in], [[dnl -translit(`abcdeabcde', `a') -translit(`abcdeabcde', `ab') -translit(`abcdeabcde', `a', `f') -translit(`abcdeabcde', `aa', `fg') -translit(`abcdeabcde', `a', `fg') -translit(`abcdeabcde', `ab', `f') -translit(`abcdeabcde', `ab', `fg') -translit(`abcdeabcde', `ab', `ba') -translit(`abcdeabcde', `e', `f') -translit(`abc', `', `cde') -translit(`', `a', `bc') -]]) -AT_CHECK_M4([in], [0], [[bcdebcde -cdecde -fbcdefbcde -fbcdefbcde -fbcdefbcde -fcdefcde -fgcdefgcde -bacdebacde -abcdfabcdf -abc - -]]) - -AT_CLEANUP - - - -## -------- ## -## undivert ## -## -------- ## - -AT_SETUP([undivert]) - -AT_DATA([[undivert.m4]], -[[define(`undiverted', `UNDIVERTED') -# undiverted file. -undivert(`undivert.incl') -# included file. -include(`undivert.incl') -]]) - -AT_DATA([[undivert.incl]], -[[This is to be undiverted soon. -]]) - -AT_CHECK_M4([undivert.m4], 0, -[[ -# undiverted file. -This is to be undiverted soon. - -# included file. -This is to be UNDIVERTED soon. - -]]) - -AT_CLEANUP - - - -## ---- ## -## wrap ## -## ---- ## - -AT_SETUP([wrap]) - -AT_DATA([[wrap.m4]], -[[divert(-1) -m4wrap(`Wrapper no. 1 -') - -m4wrap(`Wrapper no. 2 -m4wrap(`Wrapper no. 3 -m4wrap(`Wrapper no. 4 -')')') -divert -No. 33: The End. -]]) - -AT_CHECK_M4([wrap.m4], 0, -[[ -No. 33: The End. -Wrapper no. 1 -Wrapper no. 2 -Wrapper no. 3 -Wrapper no. 4 -]]) - -AT_CLEANUP diff --git a/tests/freeze.at b/tests/freeze.at deleted file mode 100644 index 438bcc32..00000000 --- a/tests/freeze.at +++ /dev/null @@ -1,539 +0,0 @@ -# Hand crafted tests for GNU M4. -*- Autotest -*- -# Copyright (C) 2006-2010, 2013-2014, 2017 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 . - -# AT_TEST_FREEZE([title], [text1], [text2]) -# ----------------------------------------- -# Create a test TITLE, which checks that freezing TEXT1, then reloading -# it with TEXT2, produces the same results as running TEXT1 and TEXT2 in -# a single run. -m4_define([AT_TEST_FREEZE], -[AT_SETUP([$1]) -AT_KEYWORDS([frozen]) - -AT_DATA([frozen.m4], [$2]) -AT_DATA([unfrozen.m4], [$3]) - -# First generate the `expout' output by running over the sources before -# freezing. -AT_CHECK_M4([frozen.m4 unfrozen.m4], [0], [stdout-nolog], [stderr]) - -mv stdout expout -mv stderr experr - -# Now freeze the first source file. -AT_CHECK_M4([-F frozen.m4f frozen.m4], [0], [stdout-nolog]) - -mv stdout out1 - -# Now rerun the original sequence, but using the frozen file. -AT_CHECK_M4([-R frozen.m4f unfrozen.m4], - [0], [stdout-nolog], [experr], [], [ ]) - -AT_CHECK([cat out1 stdout], [0], [expout]) - -AT_CLEANUP -]) - - -AT_BANNER([Freezing state.]) - -## ---------------- ## -## freezing failure ## -## ---------------- ## - -AT_SETUP([freezing failure]) -AT_KEYWORDS([frozen]) - -AT_CHECK_M4([-F /none/such], [1], [], -[[m4: cannot open '/none/such': No such file or directory -]]) - -if test -w /dev/full && test -c /dev/full ; then - AT_CHECK_M4([-F /dev/full], [1], [], -[[m4: unable to create frozen state: No space left on device -]]) -fi -AT_CLEANUP - - -## --------------- ## -## large diversion ## -## --------------- ## - -# Check that large diversions are handled across freeze boundaries. -# Also check for escape character handling. -AT_TEST_FREEZE([large diversion], -[M4_ONE_MEG_DEFN[divert(2)f -divert(1)hi -a\nb -]], -[[divert(3)bye -]]) - -## ---------------- ## -## loading format 1 ## -## ---------------- ## - -AT_SETUP([loading format 1]) -AT_KEYWORDS([frozen]) - -m4_if([ -Note: frozen.m4f was obtained by deleting unneeded lines from the output of -a version of m4 1.4.5 with changeword support. Deleting lines is in effect -equivalent to using undefine(name) in the input. This test ensures we -behave well with the old format, including \ parsing, disappearing builtins -(okay so long as the input does not try to use them), and restoring sane -defaults for features that were only added in version 2 frozen format. - -$ m4 --version | head -n1 -GNU M4 1.4.5 -$ cat frozen.m4 -divert(`-1') -define(`foo', `\n\ -FOO') -pushdef(`foo', `bar${1}') -define(`my_define', defn(`define')) -define(`my_changeword', defn(`changeword')) -pushdef(`my_define', `define') -pushdef(`my_define', defn(`define')) -divert(`1')dnl -foo -divert`'dnl -changequote([,])dnl -changecom([/*], [*/])dnl -dnl Implied sequence of undefine(`name') due to hand-edits -$ m4 -F frozen.m4f frozen.m4 -$ -]) -AT_DATA([frozen.m4f], -[[# This is a frozen state file generated by GNU M4 1.4.5 -V1 -Q1,1 -[] -C2,2 -/**/ -F6,6 -popdefpopdef -F13,10 -my_changewordchangeword -F9,6 -my_definedefine -T9,6 -my_definedefine -F9,6 -my_definedefine -T3,7 -foo\n\ -FOO -T3,7 -foobar${1} -F3,3 -dnldnl -D1,8 -bar${1} - -D0,0 - -# End of frozen state file -]]) - -AT_DATA([input.m4], -[[foo([2]) /* foo */ popdef([foo])foo -my_define([bar], [1])[]popdef([my_define]) bar -my_define([bar], [2])[]popdef([my_define]) bar -my_define([bar], [3])[]popdef([my_define]) bar -my_define([bar], [4])[]popdef([my_define]) bar -]]) - -AT_CHECK_M4([-R frozen.m4f input.m4], [0], -[[bar${1} /* foo */ \n\ -FOO - 1 -define 1 - 3 -my_define(bar, 4) 3 -bar${1} -]], -[[m4:input.m4:5: warning: popdef: undefined macro 'my_define' -]]) - -dnl Test rejection of v2 features in a v1 frozen file -AT_DATA([bogus.m4f], [[V1 -M2 -m4 -]]) -AT_CHECK_M4([-R bogus.m4f], [1], [], -[[m4:bogus.m4f:2: ill-formed frozen file, version 2 directive `M' encountered -]]) - -AT_CLEANUP - - -## ---------------- ## -## loading format 2 ## -## ---------------- ## - -AT_SETUP([loading format 2]) -AT_KEYWORDS([frozen]) - -AT_DATA([frozen.m4f], -[[# Handcrafted file, obeying the version 2 spec -V2 -# missing close quote should be supplied -Q1,0 -> - -# missing close comment should be supplied -C1,0 -< - -M2 -m4 -M3 -gnu -F7,7,3 -builtin -builtin -gnu -# Text to negative diversion must not crash. Catches a regression -# introduced 2007-05-28 and fixed 2007-05-31. -D-1,5 -12345 -# Check line continuations. -D1,3 -a\n\ -b -# Zero can be implied -D, - -# Testing escape sequences -T4,6 -blah --\t\477\040\X5C -# Long macro definition. Catches a regression introduced on 2007-01-20 -# and patched 2007-02-25. -T4,122 -long -01234567890123456789012345678901234567890123456789 -01234567890123456789012345678901234567890123456789 -01234567890123456789 -]]) - -AT_DATA([input.m4], -[[< comment: builtin() -builtin(>define', foo, bar) -foo -blah -]]) - -AT_CHECK_M4([-R frozen.m4f input.m4], [0], -[[< comment: builtin() - -bar -- '7 \ -a -b]]) - -dnl We don't support anything larger than format 2; make sure of that... -AT_DATA([bogus.m4f], [[# comments aren't continued\ -V3 -]]) -AT_CHECK_M4([-R bogus.m4f], [63], [], -[[m4:bogus.m4f:2: frozen file version 3 greater than max supported of 2 -]]) - -dnl Check that V appears. -AT_DATA([bogus.m4f], [[# not really a frozen file -oops -]]) -AT_CHECK_M4([-R bogus.m4f], [1], [], -[[m4:bogus.m4f:2: expecting character `V' in frozen file -]]) - -dnl M4_DIVNUM_TEST(number, [out-of-bounds]) -dnl Check for diversion number corner case handling. Simulate freezing with -dnl number as the active diversion, then reload and check that number. If -dnl OUT-OF-BOUNDS, expect reloading to reject the frozen file. -m4_define([M4_DIVNUM_TEST], [ -AT_DATA([frozen.m4f], [[V2 -M2 -m4 -M3 -gnu -T1,5 -a -\n\n\n\n\n -F6,6,2 -divnum\ - -divnum -\ -m4\ - -F6,6,2 -divert -divert -m4 -F6,6,2 -define -define -m4 -D]$1[,3 -hi - -]]) -AT_CHECK_M4([-R frozen.m4f in.m4], m4_ifval([$2], [1], [0]), -m4_ifval([$2], [], [m4_bpatsubst([$1], [^0*]) -m4_if(m4_substr([$1], [0], [1]), [-], [], [[hi -]])]), m4_ifval([$2], [[m4:frozen.m4f:24: integer overflow in frozen file -]])) -]) - -AT_DATA([in.m4], [[define(d,divnum)divert(0)d -]]) -M4_DIVNUM_TEST([02147483647]) -M4_DIVNUM_TEST([02147483648], [:]) -M4_DIVNUM_TEST([-2147483648]) -M4_DIVNUM_TEST([-2147483649], [:]) - -AT_CLEANUP - - -## --------- ## -## changecom ## -## --------- ## - -# Check that changecom/changequote are maintained across freeze boundaries. -AT_TEST_FREEZE([reloading changecom], -[[changecom`'changequote(<,>)dnl -]], -[[define(, ) -foo # foo -]]) - -## ------------ ## -## changesyntax ## -## ------------ ## - -# Check that changesyntax is maintained across freeze boundaries. -AT_TEST_FREEZE([reloading changesyntax], -[[changesyntax(`W+.', `({', `)}')dnl -define{`a.b', `hello $1'}dnl -]], -[[a.b{world} -]]) - -## --------- ## -## debugmode ## -## --------- ## - -# Check that debugmode can be preserved, and how it interacts with -d -AT_SETUP([reloading debugmode]) -AT_KEYWORDS([frozen]) - -AT_DATA([frozen.m4], -[[debugmode(`fl')dnl -]]) -AT_DATA([unfrozen.m4], -[[traceon(`len')len(`a') -]]) - -AT_CHECK_M4([-F frozen.m4f -d-V frozen.m4], [0]) - -dnl With no -d option, use the frozen file -AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0], [[1 -]], [[m4trace:unfrozen.m4:1: -1- len -]], [], [ ]) - -dnl With plain -d before -R, use the frozen file -AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0], [[1 -]], [[m4trace:unfrozen.m4:1: -1- len -]]) - -dnl With plain -d after -R, add +adeq to the frozen file -AT_CHECK_M4([-R frozen.m4f -d unfrozen.m4], [0], [[1 -]], [[m4trace:unfrozen.m4:1: -1- len(`a') -> `1' -]], [], [ ]) - -dnl With explicit -d option, override frozen file -AT_CHECK_M4([-R frozen.m4f -de unfrozen.m4], [0], [[1 -]], [[m4trace: -1- len -> 1 -]]) - -AT_CLEANUP - -## --------- ## -## nul bytes ## -## --------- ## - -# Check that NUL can be transparently preserved over freezing. -AT_SETUP([reloading nul]) -AT_KEYWORDS([frozen]) - -dnl AT_DATA can't generate NUL bytes (at least, not in all shells). -# Skip the test if printf(1) is insufficient. -AT_CHECK([printf 'define(-\0-,\0-\0)changequote([,\0])changecom(--\0)dnl -divert(1)undivert(null.out)' || exit 77], - [0], [stdout], [ignore]) -mv stdout frozen.m4 -printf 'divert(0)[divnum\0] @%:@-- len(indir(-\0-))\n' > unfrozen.m4 - -# First generate the `expout' output by running over the sources before -# freezing. -AT_CHECK_M4([-I "$abs_srcdir" frozen.m4 unfrozen.m4], [0], [stdout], [stderr]) - -mv stdout expout -mv stderr experr - -# Now freeze the first source file. -AT_CHECK_M4([-F frozen.m4f -I "$abs_srcdir" frozen.m4], [0], [stdout]) - -mv stdout out1 - -# Now rerun the original sequence, but using the frozen file. -AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0], [stdout], [experr], [], [ ]) - -AT_CHECK([cat out1 stdout], [0], [expout]) - -dnl Check that unexpected embedded NULs are recognized. -printf '# bogus frozen file\nV2\nR4\ngnu\0\n' > bogus.m4f -AT_CHECK_M4([-R bogus.m4f], [1], [], -[[m4:bogus.m4f:4: bad syntax-spec 'gnu\0' -]]) - -dnl Reject escape sequences that expand to unexpected NUL -AT_DATA([bogus.m4f], -[[# bogus frozen file -V2 -F3,4 -len -len\0 -]]) -AT_CHECK_M4([-R bogus.m4f], [1], [], -[[m4:bogus.m4f:5: ill-formed frozen file, invalid builtin 'len\0' encountered -]]) - -AT_CLEANUP -]) - -## ------- ## -## pushdef ## -## ------- ## - -# Check for pushdef stacks; broken 2001-09-01, fixed 2008-05-15. -AT_TEST_FREEZE([reloading pushdef stack], -[[pushdef(`foo', `1') -pushdef(`foo', defn(`len')) -pushdef(`foo', `3') -]], -[[foo(`abc')popdef(`foo') -foo(`ab')popdef(`foo') -foo(`a')popdef(`foo') -foo -]]) - -## ------------- ## -## regexp syntax ## -## ------------- ## - -# Check that regular expression syntax is maintained across freeze boundaries. -AT_TEST_FREEZE([reloading regexp syntax], -[[changeresyntax(`POSIX_EXTENDED')dnl -]], -[[regexp(`GNUs not Unix', `\w(\w*)$') -regexp(`GNUs not Unix', `\w\(\w*\)$', `GNU_M4') -]]) - -## ----- ## -## trace ## -## ----- ## - -# Check for macro tracing, both single and global. -AT_TEST_FREEZE([reloading traced macros], -[[define(`text', `hello world')dnl -define(`foo', `bar')dnl -traceon(`blah', `divnum', `text')dnl -traceon -]], -[[foo -traceoff -foo -text -divnum -ifdef(`blah', `', `define(`blah', `finally')')dnl -blah -]]) - -## ---------------- ## -## unknown builtins ## -## ---------------- ## - -AT_SETUP([reloading unknown builtin]) -AT_KEYWORDS([frozen]) - -AT_DATA([[empty.m4]]) - -# Freeze default state. Also check for bug fixed 18 Oct, 2007. -AT_CHECK_M4([-F frozen.m4f -t undefined empty.m4]) - -# Add an unknown builtin. -echo 'F1,1' >> frozen.m4f -echo 'a' >> frozen.m4f -echo 'b' >> frozen.m4f - -AT_DATA([[input.m4]], -[[dnl The macro is defined; checking this is safe -ifdef(`a', `yes', `no') -dnl Grabbing the definition must warn; and the copy is the empty string -define(`c', defn(`a')) -dnl Invoking the macro directly must warn -a -dnl Invoking it indirectly must warn -indir(`a') -dnl Since it is a placeholder, builtin must reject it -builtin(`b') -dnl The copy is a text string, not a placeholder -c -dnl Since it is defined, it must have a definition -dumpdef(`a', `c') -dnl Deleting it is safe -popdef(`a') -a -]]) - -AT_CHECK_M4([-R frozen.m4f input.m4], 0, -[[yes - - - - - - - -a -]], -[[m4:input.m4:4: warning: defn: a: builtin 'b' requested by frozen file not found -m4:input.m4:6: warning: a: builtin 'b' requested by frozen file not found -m4:input.m4:8: warning: a: builtin 'b' requested by frozen file not found -m4:input.m4:10: warning: builtin: undefined builtin 'b' -a: <> -c: `' -]], [], [ ]) - -AT_CLEANUP diff --git a/tests/generate.awk b/tests/generate.awk deleted file mode 100755 index f373d7f3..00000000 --- a/tests/generate.awk +++ /dev/null @@ -1,216 +0,0 @@ -# Extract all examples from the manual source. -*- AWK -*- - -# Copyright (C) 1992, 2000-2001, 2006-2010, 2013-2014, 2017 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 . - -# This script is for use with any New AWK. - -BEGIN { - seq = -1; - status = xfail = examples = 0; - file = options = ""; - print "# This file is part of the GNU m4 test suite. -*- Autotest -*-"; - # I don't know how to get this file's name, so it's hard coded :( - print "# Do not edit by hand, it was generated by generate.awk."; - print "#"; - print "# Copyright (C) 1992, 2000, 2001, 2006, 2007, 2008, 2009 Free"; - print "# Software Foundation, Inc."; - print ; - print "AT_BANNER([Documentation examples.])"; - print ; - print ; -} - -/^@node / { # Start a new test group. - if (seq > 0) - print "AT_CLEANUP"; - - split ($0, tmp, ","); - node = substr(tmp[1], 7); - seq = 0; -} - -/^@comment file: / { # Produce a data file instead of a test. - file = $3; -} - -/^@comment options: / { # Pass additional options to m4. - options = $0; - gsub ("@comment options:", "", options); -} - -/^@comment xfail$/ { # Expect the test to fail. - xfail = 1; -} - -/^@comment examples$/ { # The test uses files from the examples dir. - examples = 1; -} - -/^@comment ignore$/ { # This is just formatted doc text, not an actual test. - getline; - status = xfail = examples = 0; - options = file = ""; - next; -} - -/^@comment status: / { # Expected exit status of a test. - status = $3; -} - -/^@example$/, /^@end example$/ { # The body of the test. - if (seq < 0) - next; - - if ($0 ~ /^@example$/) - { - if (seq == 0) - new_group(node); - seq++; - printf ("echo \"$at_srcdir/%s:%d:\"\n", FILENAME, NR) - next; - } - - if ($0 ~ /^@end example$/) - { - if (file != "") - { - if (output || error) - { - fatal("while getting file " file \ - " found output = " output "," \ - " found error = " error); - } - input = normalize(input); - printf ("AT_DATA([[%s]],\n[[%s]])\n\n", file, input); - } - else - { - new_test(input, status, output, error, options, xfail, examples); - } - status = xfail = examples = 0; - file = input = output = error = options = ""; - next; - } - - if ($0 ~ /^\^D$/) - next; - if ($0 ~ /^\$ @kbd/) - next; - - if ($0 ~ /^@result\{\}/) - output = output $0 "\n"; - else if ($0 ~ /^@error\{\}/) - error = error $0 "\n"; - else - input = input $0 "\n"; -} - -END { - if (seq > 0) - print "AT_CLEANUP"; -} - -# We have to handle CONTENTS line per line, since anchors in AWK are -# referring to the whole string, not the lines. -function normalize(contents, i, lines, n, line, res) { - # Remove the Texinfo tags. - n = split (contents, lines, "\n"); - # We don't want the last field which empty: it's behind the last \n. - for (i = 1; i < n; ++i) - { - line = lines[i]; - gsub ("^@result[{]}", "", line); - gsub ("^@error[{]}", "", line); - gsub ("@[{]", "{", line); - gsub ("@}", "}", line); - gsub ("@@", "@", line); - gsub ("@tabchar[{]}", "\t", line); - gsub ("@w[{] }", " @\\&t@", line); - gsub ("m4_", "m@\\&t@4_", line); - - # Some of the examples have improperly balanced square brackets. - gsub ("[[]", "@<:@", line); - gsub ("[]]", "@:>@", line); - - res = res line "\n"; - } - return res; -} - -function new_group(node) { - banner = node ". "; - gsub (".", "-", banner); - printf ("\n\n"); - printf ("## %s ##\n", banner); - printf ("## %s. ##\n", node); - printf ("## %s ##\n", banner); - printf ("\n"); - printf ("AT_SETUP([%s])\n", node); - printf ("AT_KEYWORDS([[documentation]])\n\n"); -} - -function new_test(input, status, output, error, options, xfail, examples) { - input = normalize(input); - output = normalize(output); - error = normalize(error); - - if (error == "ignore\n") - error = "ignore"; - - if (options ~ / mpeval/) - printf ("AT_CHECK_GMP\n"); - if (xfail == 1) - printf ("AT_XFAIL_IF([:])\n"); - - if (examples == 1) - { - printf ("AT_DATA([expout1],\n[[%s]])\n", output); - printf ("$SED -e \"s|doc/examples|$abs_top_srcdir/doc/examples|g\" \\\n"); - printf (" < expout1 > expout\n\n"); - if (error) - { - printf ("AT_DATA([experr1],\n[[%s]])\n", error); - printf ("$SED \"s|doc/examples|$abs_top_srcdir/doc/examples|g\" \\\n"); - printf (" < experr1 > experr\n\n"); - } - options = options " -I\"$abs_top_srcdir/doc/examples\""; - } - - printf ("AT_DATA([[input.m4]],\n[[%s]])\n\n", input); - # Some of these tests `include' files from tests/. - printf ("AT_CHECK_M4([[%s]], %s,", options, status); - if (examples == 1) - printf ("\n[expout]"); - else if (output) - printf ("\n[[%s]]", output); - else - printf (" []"); - if (examples == 1 && error) - printf (",\n[experr]"); - else if (error) - printf (",\n[[%s]]", error); - else - printf (", []"); - printf (", [[input.m4]])\n\n"); -} - -function fatal(msg) { - print "generate.awk: " FILENAME ":" NR ": " msg > "/dev/stderr" - exit 1 -} diff --git a/tests/import.c b/tests/import.c deleted file mode 100644 index cdd1176c..00000000 --- a/tests/import.c +++ /dev/null @@ -1,110 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 2003, 2006-2008, 2010, 2013-2014, 2017 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 . -*/ - -#include - -/* Build using only the exported interfaces, unless NDEBUG is set, in - which case use private symbols to speed things up as much as possible. */ -#ifndef NDEBUG -# include -#else -# include "m4private.h" -#endif - -/* function macros blind side minargs maxargs */ -#define builtin_functions \ - BUILTIN (import, false, false, false, 0, 1) \ - BUILTIN (symbol_fail, false, false, false, 0, 1) \ - BUILTIN (module_fail, false, false, false, 0, 1) \ - -#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN (handler) - builtin_functions -#undef BUILTIN - -static const m4_builtin m4_builtin_table[] = -{ -#define BUILTIN(handler, macros, blind, side, min, max) \ - M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max) - - builtin_functions -#undef BUILTIN - - { NULL, NULL, 0, 0, 0 }, -}; - - -void -include_import (m4 *context, m4_module *module, m4_obstack *obs) -{ - m4_install_builtins (context, module, m4_builtin_table); -} - - - -typedef bool export_test_func (const char *); -typedef bool no_such_func (const char *); - -/** - * import() - **/ -M4BUILTIN_HANDLER (import) -{ - M4_MODULE_IMPORT (modtest, export_test); - - const char *s = "`import'::`import' called."; - - assert (obs != 0); - obstack_grow (obs, s, strlen(s)); - - if (export_test && export_test (M4ARG (1))) - fputs ("TRUE\n", stderr); -} - -/** - * symbol_fail() - **/ -M4BUILTIN_HANDLER (symbol_fail) -{ - M4_MODULE_IMPORT (modtest, no_such); - - const char *s = "`import'::`symbol_fail' called."; - - assert (obs != 0); - obstack_grow (obs, s, strlen(s)); - - if (no_such && no_such (M4ARG (1))) - fputs ("TRUE\n", stderr); -} - -/** - * module_fail() - **/ -M4BUILTIN_HANDLER (module_fail) -{ - M4_MODULE_IMPORT (no_such, no_such); - - const char *s = "`import'::`module_fail' called."; - - assert (obs != 0); - obstack_grow (obs, s, strlen(s)); - - if (no_such && no_such (M4ARG (1))) - fputs ("TRUE\n", stderr); -} diff --git a/tests/iso8859.m4 b/tests/iso8859.m4 deleted file mode 100644 index 8ffb7532..00000000 Binary files a/tests/iso8859.m4 and /dev/null differ diff --git a/tests/m4.in b/tests/m4.in deleted file mode 100644 index 49d456c2..00000000 --- a/tests/m4.in +++ /dev/null @@ -1,46 +0,0 @@ -#! /bin/sh -# @configure_input@ -# Wrapper around a non installed m4 to make it work as an installed one. -# -# Copyright (C) 2001-2002, 2006-2008, 2010, 2013-2014, 2017 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 . -# -# Written by Gary V. Vaughan - -# Be Bourne compatible -if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then - emulate sh - NULLCMD=: - # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which - # is contrary to our usage. Disable this feature. - alias -g '${1+"$@"}'='"$@"' - setopt NO_GLOB_SUBST -else - case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac -fi - -M4PATH="\ -@abs_top_builddir@/modules/.libs:\ -@abs_top_builddir@/tests/.libs:\ -${M4PATH+$M4PATH:}\ -:" -export M4PATH - -exec "@abs_top_builddir@/src/m4" \ - ${1+"$@"} -exit 1 diff --git a/tests/macros.at b/tests/macros.at deleted file mode 100644 index 2f8d5ba6..00000000 --- a/tests/macros.at +++ /dev/null @@ -1,589 +0,0 @@ -# Hand crafted tests for GNU M4. -*- Autotest -*- -# Copyright (C) 2001, 2006-2008, 2010, 2013-2014, 2017 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 . - -AT_BANNER([Macro definitions.]) - -# Checking everything related to macro definitions: the expansion of -# user macros, the propagation of various bits (tracing, number of -# arguments and so on). - -## ---------------- ## -## Arity and defn. ## -## ---------------- ## - -AT_SETUP([Arity and defn]) - -# Check that the arity checking of define is correctly propagated. - -AT_DATA([[input.m4]], -[[define(`defun', defn(`define')) -define -define(`foo') -define(`foo', `bar') -define(`foo', `bar', `baz') - -defun -defun(`foo') -defun(`foo', `bar') -defun(`foo', `bar', `baz') -]]) - -AT_DATA([[expout]], -[[ -define - - - - -defun - - - -]]) - -AT_CHECK_M4([input.m4], 0, [expout], -[[m4:input.m4:5: warning: define: extra arguments ignored: 3 > 2 -m4:input.m4:10: warning: defun: extra arguments ignored: 3 > 2 -]]) - -AT_CLEANUP - - -## ------------------------- ## -## Arity, defn, and freeze. ## -## ------------------------- ## - -AT_SETUP([Arity, defn, and freeze]) -AT_KEYWORDS([frozen]) - -AT_DATA([[freezeme.m4]], -[[define(`defun', defn(`define'))dnl -undefine(`define')dnl -]]) - -AT_CHECK_M4([--freeze-state=frozen.m4f freezeme.m4], 0) - -AT_DATA([[input.m4]], -[[defun -defun(`foo') -defun(`foo', `bar') -defun(`foo', `bar', `baz') -]]) - -AT_DATA([[expout]], -[[defun - - - -]]) - -AT_CHECK_M4([--reload-state=frozen.m4f input.m4], 0, expout, -[[m4:input.m4:4: warning: defun: extra arguments ignored: 3 > 2 -]]) - -AT_CLEANUP(freezeme.m4 frozen.m4f) - - -## ------------------- ## -## Command line define ## -## ------------------- ## - -AT_SETUP([Command line define]) - -dnl Test that -D after last file still affects m4wrap'd text. -AT_DATA([in1], [[m4wrap(`foo -')foo -]]) -AT_DATA([in2], [[foo -]]) -AT_CHECK_M4([-Dfoo=1 in1 -Dfoo=2 in2 -Dfoo=3], [0], -[[1 -2 -3 -]]) - -dnl Test that -D only affects top-most definition. -AT_DATA([in1], [[define(`foo', `1')pushdef(`foo', `2')dnl -]]) -AT_DATA([in2], [[foo -popdef(`foo')foo -popdef(`foo')foo -]]) -AT_CHECK_M4([in1 -Dfoo=3 in2], [0], -[[3 -1 -foo -]]) - -dnl Test that -D and -U interact in correct order -AT_DATA([in], [[foo -]]) -AT_CHECK_M4([-Dfoo=bar in -Ufoo in], [0], [[bar -foo -]]) -AT_CHECK_M4([-Ufoo in -Dfoo=bar in], [0], [[foo -bar -]]) - -dnl Test macro arguments defined via -D -AT_DATA([in], [[-foo-foo(1)-foo(1,2)- --bar-bar(1)-bar(1,2)- -]]) -AT_CHECK_M4([-Dfoo -Dbar='$@' in], [0], -[[---- ---1-1,2- -]]) - -AT_CLEANUP - - - -## -------------------- ## -## Command line pushdef ## -## -------------------- ## - -AT_SETUP([Command line pushdef]) - -dnl Test that -p after last file still affects m4wrap'd text. -AT_DATA([in1], [[m4wrap(`foo -')foo -]]) -AT_DATA([in2], [[foo -]]) -AT_CHECK_M4([-pfoo=1 in1 -pfoo=2 in2 -pfoo=3], [0], -[[1 -2 -3 -]]) - -dnl Test that -p adds a definition. -AT_DATA([in1], [[define(`foo', `1')pushdef(`foo', `2')dnl -]]) -AT_DATA([in2], [[foo -popdef(`foo')foo -popdef(`foo')foo -]]) -AT_CHECK_M4([in1 -pfoo=3 in2], [0], -[[3 -2 -1 -]]) - -dnl Test that --pushdef and --popdef interact in correct order -AT_DATA([in], [[foo -]]) -AT_CHECK_M4([-Dfoo=1 --pushdef=foo=2 in --popdef=foo in], [0], -[[2 -1 -]]) -AT_CHECK_M4([--popdef=foo in --pushdef=foo=1 in], [0], -[[foo -1 -]]) - -AT_CLEANUP - - - -## ---------------- ## -## pushdef/popdef. ## -## ---------------- ## - -AT_SETUP([pushdef/popdef]) - -AT_DATA([[pushpop.m4]], -[[divert(-1) -pushdef(`hej', `def 1.') -dumpdef(`hej') -pushdef(`hej', `def 2.') -dumpdef(`hej') -pushdef(`hej', `def 3.') -dumpdef(`hej') -pushdef(`hej', `def 4.') -dumpdef(`hej') - -popdef(`hej') -dumpdef(`hej') -popdef(`hej') -dumpdef(`hej') -popdef(`hej') -dumpdef(`hej') -popdef(`hej') -dumpdef(`hej') - -dumpdef(`mac2') -popdef(`mac2') -]]) - -AT_CHECK_M4([pushpop.m4], 0, [], -[[hej: `def 1.' -hej: `def 2.' -hej: `def 3.' -hej: `def 4.' -hej: `def 3.' -hej: `def 2.' -hej: `def 1.' -m4:pushpop.m4:18: warning: dumpdef: undefined macro 'hej' -m4:pushpop.m4:20: warning: dumpdef: undefined macro 'mac2' -m4:pushpop.m4:21: warning: popdef: undefined macro 'mac2' -]]) - -AT_CLEANUP - - - -## ---------------------- ## -## Tracing Hanoi Towers. ## -## ---------------------- ## - -AT_SETUP([Tracing Hanoi Towers]) - -AT_DATA([[trace.m4]], -[[divert(-1) - -# move(from, to) -define(`move', `Move one disk from `$1' to `$2'. -') - -# _hanoi (cnt, from, to, aux) -define(`_hanoi', `ifelse(eval(`$1'<=1), 1, `move($2, $3)', -`_hanoi(decr($1), $2, $4, $3)move($2, $3)_hanoi(decr($1), $4, $3, $2)')') - -# hanoi (cnt) -define(`hanoi', `_hanoi(`$1', source, destination, auxilliary)') -divert`'dnl - -# Debugmode t -debugmode(`t') -hanoi(2) - -# Debugmode taeq -debugmode(`taeq') -hanoi(2) - -# Debugmode OFF -debugmode -hanoi(2) - -# Debugmode ae -debugmode(`ae') -traceon(`move', `_hanoi') -hanoi(2) -]]) - -AT_DATA([[expout]], -[[ -# Debugmode t - -Move one disk from source to auxilliary. -Move one disk from source to destination. -Move one disk from auxilliary to destination. - - -# Debugmode taeq - -Move one disk from source to auxilliary. -Move one disk from source to destination. -Move one disk from auxilliary to destination. - - -# Debugmode OFF - -Move one disk from source to auxilliary. -Move one disk from source to destination. -Move one disk from auxilliary to destination. - - -# Debugmode ae - - -Move one disk from source to auxilliary. -Move one disk from source to destination. -Move one disk from auxilliary to destination. - -]]) - -AT_DATA([[experr]], -[[m4trace: -1- hanoi -m4trace: -1- _hanoi -m4trace: -2- eval -m4trace: -1- ifelse -m4trace: -2- decr -m4trace: -1- _hanoi -m4trace: -2- eval -m4trace: -1- ifelse -m4trace: -1- move -m4trace: -1- move -m4trace: -2- decr -m4trace: -1- _hanoi -m4trace: -2- eval -m4trace: -1- ifelse -m4trace: -1- move -m4trace: -1- debugmode -m4trace: -1- hanoi(`2') -> `_hanoi(`2', source, destination, auxilliary)' -m4trace: -1- _hanoi(`2', `source', `destination', `auxilliary') -> `ifelse(eval(`2'<=1), 1, `move(source, destination)', -`_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)')' -m4trace: -2- eval(`2<=1') -> `0' -m4trace: -1- ifelse(`0', `1', `move(source, destination)', `_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)') -> `_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)' -m4trace: -2- decr(`2') -> `1' -m4trace: -1- _hanoi(`1', `source', `auxilliary', `destination') -> `ifelse(eval(`1'<=1), 1, `move(source, auxilliary)', -`_hanoi(decr(1), source, destination, auxilliary)move(source, auxilliary)_hanoi(decr(1), destination, auxilliary, source)')' -m4trace: -2- eval(`1<=1') -> `1' -m4trace: -1- ifelse(`1', `1', `move(source, auxilliary)', `_hanoi(decr(1), source, destination, auxilliary)move(source, auxilliary)_hanoi(decr(1), destination, auxilliary, source)') -> `move(source, auxilliary)' -m4trace: -1- move(`source', `auxilliary') -> `Move one disk from `source' to `auxilliary'. -' -m4trace: -1- move(`source', `destination') -> `Move one disk from `source' to `destination'. -' -m4trace: -2- decr(`2') -> `1' -m4trace: -1- _hanoi(`1', `auxilliary', `destination', `source') -> `ifelse(eval(`1'<=1), 1, `move(auxilliary, destination)', -`_hanoi(decr(1), auxilliary, source, destination)move(auxilliary, destination)_hanoi(decr(1), source, destination, auxilliary)')' -m4trace: -2- eval(`1<=1') -> `1' -m4trace: -1- ifelse(`1', `1', `move(auxilliary, destination)', `_hanoi(decr(1), auxilliary, source, destination)move(auxilliary, destination)_hanoi(decr(1), source, destination, auxilliary)') -> `move(auxilliary, destination)' -m4trace: -1- move(`auxilliary', `destination') -> `Move one disk from `auxilliary' to `destination'. -' -m4trace: -1- debugmode -> `' -m4trace: -1- _hanoi(2, source, destination, auxilliary) -> ifelse(eval(`2'<=1), 1, `move(source, destination)', -`_hanoi(decr(2), source, auxilliary, destination)move(source, destination)_hanoi(decr(2), auxilliary, destination, source)') -m4trace: -1- _hanoi(1, source, auxilliary, destination) -> ifelse(eval(`1'<=1), 1, `move(source, auxilliary)', -`_hanoi(decr(1), source, destination, auxilliary)move(source, auxilliary)_hanoi(decr(1), destination, auxilliary, source)') -m4trace: -1- move(source, auxilliary) -> Move one disk from `source' to `auxilliary'. - -m4trace: -1- move(source, destination) -> Move one disk from `source' to `destination'. - -m4trace: -1- _hanoi(1, auxilliary, destination, source) -> ifelse(eval(`1'<=1), 1, `move(auxilliary, destination)', -`_hanoi(decr(1), auxilliary, source, destination)move(auxilliary, destination)_hanoi(decr(1), source, destination, auxilliary)') -m4trace: -1- move(auxilliary, destination) -> Move one disk from `auxilliary' to `destination'. - -]]) - -AT_CHECK_M4([trace.m4], 0, expout, experr) - -AT_CLEANUP - - - -## ------------------------------- ## -## Propagation of trace requests. ## -## ------------------------------- ## - -AT_SETUP([Propagation of traceon]) - -AT_DATA([[trace2.m4]], -[[traceon(`define') -debugmode(`aeq') - -# copy the `define' builtin definition to another symbol -define(`my_define', defn(`define')) - -# delete the original -undefine(`define') - -# Does it work? -my_define(`foo', `bar') - -# Use the new definition to redefine the original symbol -my_define(`define', defn(`my_define')) - -# Torture the flag propogation -undefine(`my_define') -define(`my_define', defn(`define')) - -# There are now 2 symbols pointing to the same builtin function -my_define(`foo', `bar') -define(`foo', `bar') -]]) - -AT_DATA([[expout]], -[[ - - -# copy the `define' builtin definition to another symbol - - -# delete the original - - -# Does it work? - - -# Use the new definition to redefine the original symbol - - -# Torture the flag propogation - - - -# There are now 2 symbols pointing to the same builtin function - - -]]) - -AT_DATA([[experr]], -[[m4trace: -1- define(`my_define', ) -> `' -m4trace: -1- define(`my_define', ) -> `' -m4trace: -1- define(`foo', `bar') -> `' -]]) - -AT_CHECK_M4([trace2.m4], 0, expout, experr) - -AT_CLEANUP - - - -## ------------------------ ## -## Propagation of --trace. ## -## ------------------------ ## - -AT_SETUP([Propagation of --trace]) - -AT_DATA([[trace3.m4]], -[[# copy the `define' builtin definition to another symbol -define(`my_define', defn(`define')) - -# delete the original -undefine(`define') - -# Does it work? -my_define(`foo', `bar') - -# Use the new definition to redefine the original symbol -my_define(`define', defn(`my_define')) - -# Torture the flag propogation -undefine(`my_define') -define(`my_define', defn(`define')) - -# There are now 2 symbols pointing to the same builtin function -my_define(`foo', `bar') -define(`foo', `bar') -]]) - -AT_DATA([[expout]], -[[# copy the `define' builtin definition to another symbol - - -# delete the original - - -# Does it work? - - -# Use the new definition to redefine the original symbol - - -# Torture the flag propogation - - - -# There are now 2 symbols pointing to the same builtin function - - -]]) - -AT_DATA([[experr]], -[[m4trace: -1- define(`my_define', ) -> `' -m4trace: -1- define(`my_define', ) -> `' -m4trace: -1- define(`foo', `bar') -> `' -]]) - -AT_CHECK_M4([-t define -daeq trace3.m4], 0, expout, experr) - -AT_CLEANUP - - -## --------------------- ## -## Renamesyms collisions ## -## --------------------- ## - -AT_SETUP([Renamesyms collisions]) - -dnl FIXME - We should gracefully detect rename collisions, rather than -dnl violating the invariants of the symbol table. -AT_XFAIL_IF([:]) - -AT_DATA([in], [[define(`bar', `1')define(`baz', `2')dnl -renamesyms(`^ba.$', `baa') -]]) - -AT_CHECK_M4([in], [0], [[ -]], [ignore]) - -AT_CLEANUP - - -## ----------------- ## -## Rescanning macros ## -## ----------------- ## - -AT_SETUP([Rescanning macros]) - -dnl This is a series of tests that used to be included as undocumented tests -dnl in the branch m4.texinfo. They exercise rescanning issues not stressed -dnl anywhere else in the suite, but which are used by autoconf. -AT_DATA([in], [[define(`x1', `len(`$1'')dnl -define(`y1', ``$1')')dnl -x1(`01234567890123456789')y1(`98765432109876543210') -]]) - -AT_CHECK_M4([in], [0], [[40 -]]) - -AT_DATA([in], [[define(`echo', `$@')dnl -define(`foo', echo(`01234567890123456789')echo(`98765432109876543210'))dnl -foo -]]) - -AT_CHECK_M4([in], [0], [[0123456789012345678998765432109876543210 -]]) - -AT_DATA([in], [[define(`a', `A')define(`echo', `$@')define(`join', `$1$2')dnl -define(`abcdefghijklmnopqrstuvwxyz', `Z')dnl -join(`a', `bcdefghijklmnopqrstuvwxyz') -join(`a', echo(`bcdefghijklmnopqrstuvwxyz')) -]]) - -AT_CHECK_M4([in], [0], [[Z -Z -]]) - -AT_DATA([in], [[define(`echo', `$@')dnl -echo(echo(`01234567890123456789', `01234567890123456789') -echo(`98765432109876543210', `98765432109876543210')) -len((echo(`01234567890123456789', - `01234567890123456789')echo(`98765432109876543210', - `98765432109876543210'))) -indir(`echo', indir(`echo', `01234567890123456789', - `01234567890123456789') -indir(`echo', `98765432109876543210', `98765432109876543210')) -define(`argn', `$#')dnl -define(`echo1', `-$@-')define(`echo2', `,$@,')dnl -echo1(`1', `2', `3') argn(echo1(`1', `2', `3')) -echo2(`1', `2', `3') argn(echo2(`1', `2', `3')) -]]) - -AT_CHECK_M4([in], [0], [[01234567890123456789,01234567890123456789 -98765432109876543210,98765432109876543210 -84 -01234567890123456789,01234567890123456789 -98765432109876543210,98765432109876543210 --1,2,3- 3 -,1,2,3, 5 -]]) - -AT_CLEANUP diff --git a/tests/modtest.c b/tests/modtest.c deleted file mode 100644 index ad6d91b2..00000000 --- a/tests/modtest.c +++ /dev/null @@ -1,101 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1999-2001, 2003-2004, 2006-2008, 2010, 2013-2014, 2017 - 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 . -*/ - -#include - -/* Build using only the exported interfaces, unless NDEBUG is set, in - which case use private symbols to speed things up as much as possible. */ -#ifndef NDEBUG -# include -#else -# include "m4private.h" -#endif - -extern bool export_test (const char *foo); - -/* function macros blind side minargs maxargs */ -#define builtin_functions \ - BUILTIN (test, false, false, false, 0, 0) - -#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN (handler) - builtin_functions -#undef BUILTIN - -static const m4_builtin m4_builtin_table[] = -{ -#define BUILTIN(handler, macros, blind, side, min, max) \ - M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max) - - builtin_functions -#undef BUILTIN - - { NULL, NULL, 0, 0, 0 }, -}; - -static const m4_macro m4_macro_table[] = -{ - /* name text min max */ - { "__test__", "`modtest'", 0, 0 }, - { "onearg", "$1", 1, 1 }, - { "manyargs", "$@", 0, SIZE_MAX }, - { NULL, NULL, 0, 0 }, -}; - - - -/** - * modtest() - **/ -void -include_modtest (m4 *context, m4_module *module, m4_obstack *obs) -{ - const char *s = "Test module loaded.\n"; - - m4_install_builtins (context, module, m4_builtin_table); - m4_install_macros (context, module, m4_macro_table); - - /* Don't depend on OBS so that the traces are the same when used - directly, or via a frozen file. */ - fputs (s, stderr); -} - - -/** - * test() - **/ -M4BUILTIN_HANDLER (test) -{ - const char *s = "Test module called."; - - assert (obs != 0); - obstack_grow (obs, s, strlen(s)); -} - - -/** - * export_test() - **/ -bool -export_test (const char *foo) -{ - if (foo) - xfprintf (stderr, "%s\n", foo); - return (bool) (foo != 0); -} diff --git a/tests/modules.at b/tests/modules.at deleted file mode 100644 index f4e5485b..00000000 --- a/tests/modules.at +++ /dev/null @@ -1,344 +0,0 @@ -# Hand crafted tests for GNU M4. -*- Autotest -*- -# Copyright (C) 2001, 2006-2008, 2010, 2013-2014, 2017 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 . - - -AT_BANNER([Module support.]) - - -## --------- ## -## modfreeze ## -## --------- ## - -AT_SETUP([Freezing modules]) -AT_KEYWORDS([frozen]) - -AT_DATA([[frozen.m4]], -[[divert(1)dnl -define(`test', `local::`test'')dnl -define(`test1', defn(`test'))dnl -->test -include(`modtest') -define(`test2', defn(`test'))dnl -->test -include(`shadow') -define(`test3', defn(`test'))dnl -->test -]]) - -AT_DATA([[unfrozen.m4]], -[[undivert(1)dnl -test1 -test2 -test3 -]]) - -# First generate the `expout' ouput by running over the sources before -# freezing. -AT_CHECK_M4([-I "$abs_builddir" frozen.m4 unfrozen.m4], - [0], [stdout], [stderr]) - -mv stdout expout -mv stderr experr - -# Now freeze the first source file. -AT_CHECK_M4([-I "$abs_builddir" -F frozen.m4f frozen.m4], - [0], [], [ignore]) - -# Now rerun the original sequence, but using the frozen file. -AT_CHECK_M4([-I "$abs_builddir" -R frozen.m4f unfrozen.m4], - [0], [expout], [experr]) - -AT_CLEANUP([frozen.m4f]) - - -## ---------------------------- ## -## Exercising the test module. ## -## ---------------------------- ## - -# AT_CHECK_M4_MODTEST(TITLE, ENV-VARS, M4-OPTIONS) -# ------------------------------------------------ -# Add a test named TITLE, running m4 with either ENV-VARS in the environment -# or M4-OPTIONS set to pick up test modules. -m4_define([AT_CHECK_M4_MODTEST], -[AT_SETUP([$1]) - -AT_DATA([input.m4], -[[test -Dumpdef: dumpdef(`test'). -include(`modtest') -test -Dumpdef: dumpdef(`test'). -]]) - -dnl Fortunately, all tests within AT_SETUP are in the same subshell, so -dnl setting the environment now will impact the AT_CHECK_M4, but not -dnl carry over to the next AT_SETUP. -m4_ifval([$2], [$2 -export m4_substr([$2], [0], m4_index([$2], [=]))]) - -AT_CHECK_M4([$3 input.m4], [0], -[[test -Dumpdef: . - -Test module called. -Dumpdef: . -]], -[[m4:input.m4:2: warning: dumpdef: undefined macro 'test' -Test module loaded. -test: -]]) - -AT_CLEANUP -]) - - - -AT_CHECK_M4_MODTEST([--include: absolute path], - [], [-I "$abs_builddir"]) - -AT_CHECK_M4_MODTEST([--include: relative path], - [], [-I "$top_build_prefix/tests"]) - -AT_CHECK_M4_MODTEST([M4PATH: absolute path], - [M4PATH="$abs_builddir:"], []) - -AT_CHECK_M4_MODTEST([M4PATH: relative path], - [M4PATH="$top_build_prefix/tests:"], []) - - - -## ------ ## -## shadow ## -## ------ ## - -AT_SETUP([modules: shadow]) - -AT_DATA([[input.m4]], -[[# no modules loaded yet -test -shadow - -# define our own macros for `test' and `shadow' -define(`test', `local::`test'') -define(`shadow', `local::`shadow'') -test -shadow - -# module Shadow defines `shadow' and `test' macros -include(`shadow') -dumpdef(`test') -dumpdef(`shadow') -test -shadow - -# save the definition of `test' from the Shadow module -define(`Shadow::test', defn(`test')) - -# module Modtest also defines a `test' macro -include(`modtest') -dumpdef(`test') -dumpdef(`shadow') -test -shadow - -# Reloading Shadow shouldn't affect anything -include(`shadow') -dumpdef(`test') -dumpdef(`shadow') -test -shadow -]]) - -AT_DATA([[expout]], -[[# no modules loaded yet -test -shadow - -# define our own macros for `test' and `shadow' - - -local::test -local::shadow - -# module Shadow defines `shadow' and `test' macros -Shadow module loaded. - - -Shadow::test called. -Shadow::shadow called. - -# save the definition of `test' from the Shadow module - - -# module Modtest also defines a `test' macro - - - -Test module called. -Shadow::shadow called. - -# Reloading Shadow shouldn't affect anything - - - -Test module called. -Shadow::shadow called. -]]) - -AT_DATA([[experr]], -[[test: -shadow: -Test module loaded. -test: -shadow: -test: -shadow: -]]) - -AT_CHECK_M4([-I "$abs_builddir" input.m4], [0], - [expout], [experr]) - -AT_CLEANUP - - - -## ----------------------- ## -## module symbol importing ## -## ----------------------- ## - -# Importing a symbol from a not yet loaded module - -# This test is ugly, because we need to canonicalize strerror strings -# to match our test. So we save STDERR to a file, and run another check -# which edits that file and compares it to the canonical STDERR output -# from the first command: - -AT_SETUP([modules: importing]) - -AT_DATA([[input.m4]], -[[import -include(`import') -import -import -symbol_fail -module_fail -]]) - -AT_DATA([[expout]], -[[import - -import::import called. -import::import called. -import::symbol_fail called. -]]) - -AT_DATA([[experr]], -[[Test module loaded. - -TRUE - -TRUE -m4:input.m4:5: cannot load symbol `no_such' from module `modtest' -m4:input.m4:6: cannot open module `no_such' -]]) - -ls "$abs_builddir" - -AT_CHECK_M4([-I "$abs_builddir" input.m4], - [1], [expout], [experr]) - -AT_CLEANUP - - - -## ------------------- ## -## text module symbols ## -## ------------------- ## - -# Support text macros with requested numbers of parameters. - -AT_SETUP([modules: text]) - -AT_DATA([input.m4], -[[__test__ -__test__(1) -__test__(1,2) -onearg -onearg(1) -onearg(1,2) -manyargs -manyargs(1) -manyargs(1,2) -]]) - -AT_CHECK_M4([-I "$abs_builddir" modtest input.m4], [0], -[[modtest -modtest -modtest - -1 -1 - -1 -1,2 -]], [[Test module loaded. -m4:input.m4:2: warning: __test__: extra arguments ignored: 1 > 0 -m4:input.m4:3: warning: __test__: extra arguments ignored: 2 > 0 -m4:input.m4:4: warning: onearg: too few arguments: 0 < 1 -m4:input.m4:6: warning: onearg: extra arguments ignored: 2 > 1 -]]) - -AT_CLEANUP - - -## -------------------- ## -## trace module symbols ## -## -------------------- ## - -# The trace bit should not be lost if a builtin is unloaded from -# memory and then redefined by a subsequent load. - -AT_SETUP([modules: trace]) - -AT_DATA([[input.m4]], -[[test -include(`shadow') -test -include(`shadow') -test -]]) - -AT_DATA([[expout]], -[[test -Shadow module loaded. -Shadow::test called. - -Shadow::test called. -]]) - -AT_DATA([[experr]], -[[m4trace: -1- test -> `Shadow::`test' called.' -m4trace: -1- test -> `Shadow::`test' called.' -]]) - - -AT_CHECK_M4([-I "$abs_builddir" -t test input.m4], - [0], [expout], [experr]) - -AT_CLEANUP diff --git a/tests/null.err b/tests/null.err deleted file mode 100644 index 50ae6272..00000000 Binary files a/tests/null.err and /dev/null differ diff --git a/tests/null.m4 b/tests/null.m4 deleted file mode 100644 index 92fb6a11..00000000 Binary files a/tests/null.m4 and /dev/null differ diff --git a/tests/null.out b/tests/null.out deleted file mode 100644 index 784ab7ab..00000000 Binary files a/tests/null.out and /dev/null differ diff --git a/tests/options.at b/tests/options.at deleted file mode 100644 index 29f41c07..00000000 --- a/tests/options.at +++ /dev/null @@ -1,863 +0,0 @@ -# Hand crafted tests for GNU M4. -*- Autotest -*- -# Copyright (C) 2001, 2006-2010, 2013-2014, 2017 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 . - -AT_BANNER([Options.]) - - -## ------------------ ## -## deprecated options ## -## ------------------ ## - -AT_SETUP([deprecated options]) - -dnl -N/--diversions was removed after 1.4.x -AT_CHECK_M4([--diversions=1], [1], [], [stderr]) -AT_CHECK([$SED 's/Try.*help/Try `m4 --help/' stderr], [0], -[[m4: bad option -Try `m4 --help' for more information. -]]) - -dnl -H/--hashsize are no-ops since 2.0 -AT_CHECK_M4([-H1 --hashsize=1], [0], [], -[[m4: warning: `-H' is deprecated -m4: warning: `--hashsize' is deprecated -]]) - -dnl -S/-T are no-ops for compatibility -AT_CHECK_M4([-S1 -T1], [0], [], -[[m4: warning: `-S' is deprecated -m4: warning: `-T' is deprecated -]]) - -dnl -Bint can be confused with its no-op meaning in 1.4.x, but all other -dnl uses of -B or its long option are okay -AT_CHECK_M4([-B1], [0], [], -[[m4: warning: recommend using `-B ./1' instead -]]) -AT_CHECK_M4([-B./1 --prepend-include=1], [0], [], -[[]]) - -dnl --error-output is a misleading name -AT_CHECK_M4([--error-output=trace], [0], [], -[[m4: warning: `--error-output' is deprecated, use `--debugfile' instead -]]) -AT_CHECK([rm trace]) - -dnl -o will change meaning in the future -AT_CHECK_M4([-otrace], [0], [], -[[m4: warning: `-o' is deprecated, use `--debugfile' instead -]]) -AT_CHECK([rm trace]) - -dnl -e is an odd spelling for --interactive -AT_CHECK_M4([-e], [0], [], -[[m4: warning: `-e' is deprecated, use `-i' instead -]]) - -dnl --arglength is an older spelling for --debuglen -AT_CHECK_M4([--arglength=10], [0], [], -[[m4: warning: `--arglength' is deprecated, use `--debuglen' instead -]]) - -AT_CHECK_M4([--arglength=x], [1], [], -[[m4: warning: `--arglength' is deprecated, use `--debuglen' instead -m4: invalid --arglength argument 'x' -]]) - -dnl --word-regexp from 1.4.x is no longer supported. Can't test for its -dnl alternate spelling -W, as that now means --warnings. -AT_CHECK_M4([[--word-regexp='[a-zA-Z0-9_]+']], [0], [], -[[m4: warning: `--word-regexp' is deprecated -]]) - -AT_CLEANUP - - -## ---------- ## -## file names ## -## ---------- ## - -AT_SETUP([file names]) - -dnl Check that all files are processed even after missing file -AT_DATA([in], [[hello world -]]) -AT_CHECK_M4([oops in], [1], [[hello world -]], [[m4: cannot open file 'oops': No such file or directory -]]) - -dnl Check that '-' means stdin, even if ./- exists. -AT_DATA([-], [[hi -]]) -AT_CHECK_M4([-], [0]) -AT_CHECK_M4([- --], [0]) -AT_CHECK_M4([-- -], [0]) -AT_CHECK_M4([./-], [0], [[hi -]]) -AT_CHECK_M4([./- --], [0], [[hi -]]) -AT_CHECK_M4([-- ./-], [0], [[hi -]]) - -AT_CLEANUP - - -## --------------- ## -## option grouping ## -## --------------- ## - -AT_SETUP([option grouping]) - -dnl this test group depends on correct settings of POSIXLY_CORRECT -if test -n "${POSIXLY_CORRECT+set}" ; then - (unset POSIXLY_CORRECT) >/dev/null 2>&1 || { - echo "Problem unsetting POSIXLY_CORRECT" - AT_CHECK([exit 77]) - } - unset POSIXLY_CORRECT -fi - -dnl This comes from the "Invoking m4" node; it was easier to write the -dnl test separately than to let generate.awk fiddle with it. -AT_DATA([a], [[foo 1 -m@&t@4_dnl() -]]) - -AT_DATA([-d+f], [[hi -]]) - -dnl First, run with GNU semantics -AT_CHECK_M4([-QPDfoo -d a -d+f], [0], [[ 1 -]]) - -AT_CHECK_M4([-Q -P -D foo -d -d+f -- a], [0], [[ 1 -]]) - -AT_CHECK_M4([-QPDfoo -d -- a -d+f], [0], [[ 1 -hi -]]) - -AT_CHECK_M4([-Q -P -D foo -d ./a ./-d+f], [0], [[ 1 -hi -]]) - -AT_CHECK_M4([--def foo --debug a], [0], [[ 1 -m@&t@4_dnl() -]]) - -AT_CHECK_M4([--define=foo --debug= -- a], [0], [[ 1 -m@&t@4_dnl() -]]) - -dnl Next, run with POSIX semantics -POSIXLY_CORRECT=1 -export POSIXLY_CORRECT - -AT_CHECK_M4([-QPDfoo -d a -d+f], [0], [[ 1 -]]) - -AT_CHECK_M4([-Q -P -D foo -d -d+f -- ./a], [0], [[ 1 -]]) - -AT_CHECK_M4([-QPDfoo -d -- a -d+f], [0], [[ 1 -hi -]]) - -AT_CHECK_M4([-Q -P -D foo -d ./a ./-d+f], [0], [[ 1 -hi -]]) - -AT_CHECK_M4([--def foo --debug a], [0], [[ 1 -m@&t@4_dnl() -]]) - -AT_CHECK_M4([--define=foo --debug= -- a], [0], [[ 1 -m@&t@4_dnl() -]]) - -AT_CLEANUP - - -## --------------- ## -## POSIXLY_CORRECT ## -## --------------- ## - -AT_SETUP([POSIXLY_CORRECT]) - -dnl this test group depends on correct settings of POSIXLY_CORRECT -if test -n "${POSIXLY_CORRECT+set}" ; then - (unset POSIXLY_CORRECT) >/dev/null 2>&1 || { - echo "Problem unsetting POSIXLY_CORRECT" - AT_CHECK([exit 77]) - } - unset POSIXLY_CORRECT -fi - -dnl By default, GNU extensions and warnings are enabled -AT_DATA([in], [[__line__ -dnl() -]]) -AT_CHECK_M4([in], [0], [[1 -]], [[m4:in:2: warning: dnl: extra arguments ignored: 1 > 0 -]]) -AT_CHECK_M4([in -g], [0], [[1 -]], [[m4:in:2: warning: dnl: extra arguments ignored: 1 > 0 -]]) -AT_CHECK_M4([in -G], [0], [[__line__ -]], [[m4:in:2: warning: dnl: extra arguments ignored: 1 > 0 -]]) -AT_CHECK_M4([in -W], [0], [[1 -]], [[m4:in:2: warning: dnl: extra arguments ignored: 1 > 0 -]]) -AT_CHECK_M4([in -Q], [0], [[1 -]]) - -dnl Next, run with POSIX semantics -POSIXLY_CORRECT=1 -export POSIXLY_CORRECT - -dnl POSIXLY_CORRECT implies -G -Q -AT_DATA([in], [[__line__ -dnl() -]]) -AT_CHECK_M4([in], [0], [[__line__ -]]) -AT_CHECK_M4([in -g], [0], [[1 -]]) -AT_CHECK_M4([in -G], [0], [[__line__ -]]) -AT_CHECK_M4([in -W], [0], [[__line__ -]], [[m4:in:2: warning: dnl: extra arguments ignored: 1 > 0 -]]) -AT_CHECK_M4([in -Q], [0], [[__line__ -]]) - -AT_CLEANUP - -## -------------- ## -## unknown option ## -## -------------- ## - -AT_SETUP([unknown option]) - -AT_CHECK_M4([--unknown], [1], [], [stderr]) -AT_CHECK([$SED 's/Try.*help/Try `m4 --help/' stderr], [0], -[[m4: bad option -Try `m4 --help' for more information. -]]) - -AT_CLEANUP - - -## --------- ## -## debugfile ## -## --------- ## - -AT_SETUP([--debugfile]) - -dnl For a while, CVS m4 mistakenly sent debug output to stdout -dnl when stdout and stderr were the same file. - -AT_DATA([[in]], [[foo -]]) - -AT_CHECK_M4([--debugfile=trace1 -tfoo -Dfoo=bar in 2>&1], [0], [[bar -]]) - -AT_CHECK_M4([--debugfile=trace2 -tfoo -Dfoo=bar in], [0], [[bar -]]) - -AT_CHECK([cmp trace1 trace2]) - -dnl m4 1.4.x mistakenly created the trace file. --help and --version -dnl should always override, even if they come later in the command line -AT_CHECK_M4([--debugfile=trace3 --help], [0], [ignore]) -AT_CHECK_M4([--debugfile=trace3 --version], [0], [ignore]) -AT_CHECK([test -f trace3], [1]) - -dnl check that trace file failure causes an error, but allows processing -AT_CHECK_M4([--debugfile=no_such_dir/trace -tfoo -Dfoo=bar in], [1], -[[bar -]], [[m4: cannot set debug file 'no_such_dir/trace': No such file or directory -m4trace: -1- foo -> `bar' -]]) - -dnl check that empty trace file discards trace data -AT_CHECK_M4([--debugfile= -tfoo -Dfoo=bar in], [0], -[[bar -]]) - -dnl check that all tracing gets diverted to the trace file. Don't use -dnl AT_CHECK_M4 on the first run, because sanitizing stderr breaks the -dnl comparison with the raw data in the trace file of the second run. -AT_CHECK([$M4 -dV in], [0], [[foo -]], [stderr]) -mv stderr expout -AT_CHECK_M4([--debugfile=trace4 -dV in], [0], [[foo -]]) -AT_CHECK([cat trace4], [0], [expout]) - -dnl check that order matters -AT_DATA([in1], [[bar -]]) -AT_DATA([in2], [[errprint(`hi -')dnl -bar -]]) -AT_CHECK_M4([-Dbar=hello -tbar --debugfile= in1 --debugfile in2], [0], -[[hello -hello -]], [[hi -m4trace: -1- bar -> `hello' -]]) - -AT_CLEANUP - - -## -------- ## -## debuglen ## -## -------- ## - -AT_SETUP([--debuglen]) - -dnl Check for argument validation. - -AT_DATA([in], -[[define(`echo', `$@')dnl -traceon(`echo')dnl -echo(`long string') -]]) - -AT_CHECK_M4([--debuglen=-1 in], [1], [], -[[m4: invalid --debuglen argument '-1' -]]) - -AT_CHECK_M4([--debuglen oops in], [1], [], -[[m4: invalid --debuglen argument 'oops' -]]) - -AT_CHECK_M4([-l 10oops in], [1], [], -[[m4: invalid suffix in -l argument '10oops' -]]) - -dnl MiB is the suffix to implict 1, resulting in 1048576 -AT_CHECK_M4([-lMiB in], [0], [[long string -]], [[m4trace: -1- echo(`long string') -> ``long string'' -]]) - -dnl this assumes size_t is no bigger than 64 bits -AT_CHECK_M4([-l 123456789012345678901234567890 in], [1], [], -[[m4: -l argument '123456789012345678901234567890' too large -]]) -AT_CHECK_M4([--debugl 123456789012345678901234567890 in], [1], [], -[[m4: --debuglen argument '123456789012345678901234567890' too large -]]) - -dnl per POSIX guidelines, this is a decimal number 10, not octal 8 -AT_CHECK_M4([-l 010 in], [0], [[long string -]], [[m4trace: -1- echo(`long strin...') -> ``long stri...' -]]) - -AT_CHECK_M4([-l 3 in], [0], [[long string -]], [[m4trace: -1- echo(`lon...') -> ``lo...' -]]) - -AT_CHECK_M4([--debuglen=3 -l0 in], [0], [[long string -]], [[m4trace: -1- echo(`long string') -> ``long string'' -]]) - -AT_CLEANUP - - -## --------- ## -## debugmode ## -## --------- ## - -AT_SETUP([--debugmode]) - -AT_DATA([[in]], -[[include(`nested')dnl -len(`abc') -]]) - -AT_DATA([[nested]], -[[m4wrap(`divnum -')dnl -]]) - -dnl AT_CHECK_M4 starts life with -d. Make sure it looks like -d+adeq. -AT_CHECK_M4([-tlen in], [0], [[3 -0 -]], [[m4trace: -1- len(`abc') -> `3' -]]) - -AT_CHECK_M4([-tlen -dfl -d in], [0], [[3 -0 -]], [[m4trace:in:2: -1- len(`abc') -> `3' -]]) - -dnl -d after file is deferred (but this is still useful for some flags). -AT_CHECK_M4([-tlen in -dfli], [0], [[3 -0 -]], [[m4trace: -1- len(`abc') -> `3' -m4debug: input from m4wrap recursion level 1 -m4debug: input from m4wrap exhausted -]]) - -dnl Test all flags. -AT_CHECK_M4([-dV in], [0], [[3 -0 -]], [[m4debug: module m4: opening file -m4debug: module m4: init hook called -m4debug: module m4: opened -m4debug: module m4: builtins loaded -m4debug: module gnu: opening file -m4debug: module gnu: init hook called -m4debug: module gnu: opened -m4debug: module gnu: builtins loaded -m4debug: module gnu: macros loaded -m4debug: path search for 'in' found 'in' -m4debug: input read from 'in' -m4trace:in:1: -1- id 1: include ... = {m4} -m4debug:in:1: path search for 'nested' found 'nested' -m4debug:in:1: input read from 'nested' -m4trace:in:1: -1- id 1: include(`nested') -> -m4trace:nested:1: -1- id 2: m4wrap ... = {m4} -m4trace:nested:1: -1- id 2: m4wrap(`divnum -') -> `' -m4trace:nested:2: -1- id 3: dnl ... = {m4} -m4trace:nested:2: -1- id 3: dnl -> `' -m4debug:nested:3: input reverted to in, line 1 -m4trace:in:1: -1- id 4: dnl ... = {m4} -m4trace:in:1: -1- id 4: dnl -> `' -m4trace:in:2: -1- id 5: len ... = {m4} -m4trace:in:2: -1- id 5: len(`abc') -> `3' -m4debug:in:3: input exhausted -m4debug: input from m4wrap recursion level 1 -m4trace:nested:1: -1- id 6: divnum ... = {m4} -m4trace:nested:1: -1- id 6: divnum -> `0' -m4debug: input from m4wrap exhausted -]]) - -dnl Test addition and subtraction of flags. -AT_CHECK_M4([--debug=-e --debugmode=+xt in], [0], [[3 -0 -]], [[m4trace: -1- id 1: include(`nested') -m4trace: -1- id 2: m4wrap(`divnum -') -m4trace: -1- id 3: dnl -m4trace: -1- id 4: dnl -m4trace: -1- id 5: len(`abc') -m4trace: -1- id 6: divnum -]]) - -dnl Test that shorter prefix is ambiguous. -AT_CHECK_M4([--debu], [1], [], [stderr]) -AT_CHECK([$SED -e 's/Try.*--help/Try `m4 --help/' stderr], [0], -[[m4: bad option -Try `m4 --help' for more information. -]]) - -AT_CLEANUP - - -## ---------------- ## -## discard comments ## -## ---------------- ## - -AT_SETUP([--discard-comments]) - -AT_DATA([[in]], -[[This is not a comment # but this is. -# This line should disappear completely. -This should not disappear. -changecom(`') -html ends. -]]) - -AT_CHECK_M4([-c in], [0], -[[This is not a comment This should not disappear. - -html ends. -]]) - -dnl check that even when discarding, a comment must be terminated by EOF -AT_DATA([in], [[changecom(`/*', `*/')dnl -/* unterminated comment -]]) -AT_CHECK_M4([--discard-comments in], [1], [], -[[m4:in:2: end of file in comment -]]) - -AT_CLEANUP - - -## -------------- ## -## fatal warnings ## -## -------------- ## - -AT_SETUP([--fatal-warnings]) - -AT_DATA([[in]], -[[dnl() -dnl() -dnl() -]]) - -dnl By default, warnings don't affect exit status -AT_CHECK_M4([in], [0], [], -[[m4:in:1: warning: dnl: extra arguments ignored: 1 > 0 -m4:in:2: warning: dnl: extra arguments ignored: 1 > 0 -m4:in:3: warning: dnl: extra arguments ignored: 1 > 0 -]]) - -dnl With one -E, exit status changes, but execution continues -AT_CHECK_M4([-E in], [1], [], -[[m4:in:1: warning: dnl: extra arguments ignored: 1 > 0 -m4:in:2: warning: dnl: extra arguments ignored: 1 > 0 -m4:in:3: warning: dnl: extra arguments ignored: 1 > 0 -]]) - -dnl With two -E, execution halts immediately -AT_CHECK_M4([--fatal-warnings --fatal-warnings in], [1], [], -[[m4:in:1: warning: dnl: extra arguments ignored: 1 > 0 -]]) - -dnl Exit status can't be affected if there were no warnings -AT_CHECK_M4([-EEQ in], [0]) - -AT_CLEANUP - - -## ---------------- ## -## help and version ## -## ---------------- ## - -AT_SETUP([--help and --version]) - -AT_CHECK_M4([--help], [0], [stdout]) -AT_CHECK([[$SED -n -e 's|Usage:.*\[OPTION\]... \[FILE\]...|success|p' stdout]], -[0], [success -]) - -AT_CHECK_M4([--version], [0], [stdout]) -AT_CHECK([[$SED -n -e 's|There is NO WARRANTY.*|success|p' stdout]], -[0], [success -]) - -dnl make sure option specified first takes precedence -AT_CHECK_M4([--help --version], [0], [stdout]) -AT_CHECK([[$SED -n -e 's|Usage:.*\[OPTION\]... \[FILE\]...|success|p' stdout]], -[0], [success -]) - -AT_CHECK_M4([--version --help], [0], [stdout]) -AT_CHECK([[$SED -n -e 's|There is NO WARRANTY.*|success|p' stdout]], -[0], [success -]) - -AT_CLEANUP - - -## ------------------ ## -## import-environment ## -## ------------------ ## - -AT_SETUP([--import-environment]) - -AT_DATA([[in]], -[[`TEST'=TEST -`ZAPPED'=ZAPPED -`OVERRIDE'=OVERRIDE -]]) - -TEST='This is an environment variable' -export TEST - -ZAPPED='This is an environment variable which we will delete' -export ZAPPED - -OVERRIDE='This is an environment variable which we will change' -export OVERRIDE - -AT_CHECK_M4([--import-environment -UZAPPED -DOVERRIDE='It is changed.' in], -[0], [[TEST=This is an environment variable -ZAPPED=ZAPPED -OVERRIDE=It is changed. -]]) - -AT_CLEANUP - - -## ------------- ## -## nesting-limit ## -## ------------- ## - -AT_SETUP([--nesting-limit]) - -dnl Check for argument validation. - -AT_DATA([in], -[[define(`echo', `$@')dnl -echo(echo(echo(echo(`nested string')))) -echo(echo(echo(echo(echo(echo(echo(echo(echo(`nested string'))))))))) -]]) - -AT_CHECK_M4([--nesting-limit=-1 in], [1], [], -[[m4: invalid --nesting-limit argument '-1' -]]) - -AT_CHECK_M4([--nesting-limit oops in], [1], [], -[[m4: invalid --nesting-limit argument 'oops' -]]) - -AT_CHECK_M4([-L 10oops in], [1], [], -[[m4: invalid suffix in -L argument '10oops' -]]) - -dnl MiB is the suffix to implict 1, resulting in 1048576 -AT_CHECK_M4([-LMiB in], [0], [[nested string -nested string -]]) - -dnl this assumes size_t is no bigger than 64 bits -AT_CHECK_M4([-L 123456789012345678901234567890 in], [1], [], -[[m4: -L argument '123456789012345678901234567890' too large -]]) -AT_CHECK_M4([--nest 123456789012345678901234567890 in], [1], [], -[[m4: --nesting-limit argument '123456789012345678901234567890' too large -]]) - -AT_CHECK_M4([-L 5 in], [1], [[nested string -]], -[[m4:in:3: recursion limit of 5 exceeded, use -L to change it -]]) - -dnl per POSIX guidelines, this is a decimal number 10, not octal 8 -AT_CHECK_M4([-L 010 in], [0], [[nested string -nested string -]]) - -AT_CHECK_M4([--nesting-limit=3 -L0 in], [0], [[nested string -nested string -]]) - -AT_CLEANUP - - -## --------------- ## -## prepend-include ## -## --------------- ## - -AT_SETUP([--prepend-include]) - -dnl Lots of data to set up. -AT_DATA([[in]], -[[include(`foo')dnl -include(`bar')dnl -include(`bad')dnl -include(`blah')dnl -]]) - -AT_CHECK([mkdir pre post]) - -AT_DATA([[pre/foo]], [[in pre/foo -]]) -AT_DATA([[foo]], [[in ./foo -]]) -AT_DATA([[bar]], [[in ./bar -]]) -AT_DATA([[post/bar]], [[in post/bar -]]) -AT_DATA([[post/blah]], [[in post/blah -]]) - -dnl Make circular links in the subdirectories, to ensure that the error -dnl message when bad cannot be opened comes from the search in ., regardless -dnl of what else was searched. -AT_CHECK([ln -s bad pre/bad]) -AT_CHECK([ln -s bad post/bad]) - -dnl Finally, see that it all works. -AT_CHECK_M4([-I post -B pre in], [1], -[[in pre/foo -in ./bar -in post/blah -]], [[m4:in:3: include: cannot open file 'bad': No such file or directory -]]) - -AT_CLEANUP - - -## ------------- ## -## regexp-syntax ## -## ------------- ## - -AT_SETUP([--regexp-syntax]) - -dnl test argument validation - -AT_DATA([[in]], [[regexp(`(', `(') -]]) - -AT_CHECK_M4([--regexp-syntax=unknown in], [1], [], -[[m4: bad syntax-spec: 'unknown' -]]) - -AT_CHECK_M4([--regexp-syntax= in], [0], [[0 -]]) - -AT_CHECK_M4([-rEXTENDED in], [0], [[ -]], [[m4:in:1: warning: regexp: bad regular expression '(': Unmatched ( or \( -]]) - -AT_CHECK_M4([-rgnu-m4 in], [0], [[0 -]]) - -AT_CHECK_M4([-r"gnu M4" in], [0], [[0 -]]) - -dnl Test behavior of -r intermixed with files -AT_CHECK_M4([-rEXTENDED in --regexp-syntax in], [0], [[ -0 -]], [[m4:in:1: warning: regexp: bad regular expression '(': Unmatched ( or \( -]]) - -AT_CLEANUP - - -## ----- ## -## safer ## -## ----- ## - -AT_SETUP([--safer]) - -dnl with --safer, the debugfile macro is crippled, but --debugfile is not -AT_DATA([[in]], -[[define(`foo', `1')foo -debugfile(`trace2') -define(`foo', `2')foo -]]) - -AT_CHECK_M4([--safer --debugfile=trace1 -t foo in], [1], -[[1 - -2 -]], [[m4:in:2: debugfile: disabled by --safer -]]) - -AT_CHECK([test -f trace2], [1]) -AT_CHECK([cat trace1], [0], -[[m4trace: -1- foo -> `1' -m4trace: -1- foo -> `2' -]]) - -dnl make sure builtin cannot bypass --safer, and that mkstemp does not -dnl create file -AT_DATA([[in]], [[builtin(`mkstemp', `./fooXXXXXX') -]]) - -AT_CHECK([echo foo*], [0], [foo* -]) - -AT_CHECK_M4([--safer in], [1], [[ -]], [[m4:in:1: mkstemp: disabled by --safer -]]) - -AT_CHECK([echo foo*], [0], [foo* -]) - -AT_CLEANUP - - -## ---------- ## -## syncoutput ## -## ---------- ## - -AT_SETUP([--syncoutput]) - -dnl -s/--synclines implies --syncoutput=1 -AT_DATA([in], [[hi -]]) -AT_CHECK_M4([-s in], [0], -[[#line 1 "in" -hi -]]) -AT_CHECK_M4([--synclines in], [0], -[[#line 1 "in" -hi -]]) - -dnl test intermixing option and files -AT_CHECK_M4([in --syncoutput=1 in --syncoutput in], [0], -[[hi -#line 1 "in" -hi -hi -]]) - -dnl test parse error -AT_CHECK_M4([--syncoutput=huh in], [0], -[[hi -]], [[m4: warning: --syncoutput: unknown directive 'huh' -]]) - -AT_CLEANUP - -AT_SETUP([--syncoutput and diversions]) - -dnl synclines should always start at the beginning of a line. -dnl this does not (yet) happen reliably when diversions do not -dnl always end in newline -AT_XFAIL_IF([:]) -AT_DATA([in.m4], [[divert(2)2divert(1)1 -dnl -undivert -]]) - -AT_CHECK_M4([-s in.m4], [0], [[1 -#line 1 "stdin" -2 -]]) - -AT_CLEANUP - - -## -------------------- ## -## traceon and traceoff ## -## -------------------- ## - -AT_SETUP([--traceon and --traceoff]) - -dnl test intermixing with files -AT_DATA([[in]], [[divnum -]]) -AT_CHECK_M4([-d+x in --traceon=divnum in --traceoff=divnum in], [0], -[[0 -0 -0 -]], [[m4trace: -1- id 2: divnum -> `0' -]]) - -dnl test that --traceoff does not warn on untraced name -AT_CHECK_M4([--traceoff=unknown], [0]) - -AT_CLEANUP diff --git a/tests/others.at b/tests/others.at deleted file mode 100644 index 1b035eb4..00000000 --- a/tests/others.at +++ /dev/null @@ -1,980 +0,0 @@ -# Hand crafted tests for GNU M4. -*- Autotest -*- -# Copyright (C) 2001, 2006-2010, 2013-2014, 2017 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 . - -AT_BANNER([Composite macros and other tests.]) - - -## ---------- ## -## capitalize ## -## ---------- ## - -AT_TEST_M4([Capitalize], -[[dnl -dnl convert to upper- resp. lowercase -define(`upcase', `translit(`$*', `a-z', `A-Z')') -define(`downcase', `translit(`$*', `A-Z', `a-z')') -upcase(`Convert to upper case') -downcase(`Convert To LOWER Case') -dnl -dnl capitalize a single word -define(`capitalize1', `regexp(`$1', `^\(\w\)\(\w*\)', `upcase(`\1')`'downcase(`\2')')') -define(`capitalize', `patsubst(`$1', `\w+', ``'capitalize1(`\&')')') -capitalize(`This sentence should be capitalized') -]], -[[ - -CONVERT TO UPPER CASE -convert to lower case - - -This Sentence Should Be Capitalized -]]) - - - -## -------- ## -## comments ## -## -------- ## - -AT_SETUP([Comments]) - -AT_DATA([input.m4], -[[# An ordinary comment -define(`foo', # A comment in a macro -`Macro `foo' expansion') -foo -define(`comment', `*** Macro `comment' expansion ***') -changecom(`@', `@') -foo -]]) - -AT_CHECK_M4([input.m4], [0], -[[# An ordinary comment - -# A comment in a macro -Macro foo expansion - - -# A *** Macro comment expansion *** in a macro -Macro foo expansion -]]) - -dnl Detect regression in 1.4.10b in regards to reparsing comments. -AT_DATA([input.m4], -[[define(`e', `$@')define(`q', ``$@'')define(`foo', `bar') -q(e(`one -',#two ' foo -)) -changecom(`<', `>')define(`n', `$#') -n(e(<`>, <'>)) -len(e(<`>, ,<'>)) -]]) - -AT_CHECK_M4([input.m4], [0], -[[ -`one -',`#two bar -'' - -1 -12 -]]) - -AT_CLEANUP - -## --------- ## -## countdown ## -## --------- ## - -AT_SETUP([countdown]) - -AT_DATA([[exp.m4]], -[[define(`countdown', `$1 -ifelse(eval($1 > 0), 1, `countdown(decr($1))', `Done')')dnl -countdown(7) -]]) - -AT_CHECK_M4([exp.m4], 0, -[[7 -6 -5 -4 -3 -2 -1 -0 -Done -]]) - -AT_CLEANUP - - -## --------- ## -## directory ## -## --------- ## - -AT_SETUP([directory]) - -AT_DATA([in1.m4], -[[include(`in2.m4/') -]]) -AT_DATA([in2.m4], -[[sinclude(`in2.m4/') -sinclude(`.') -]]) -AT_DATA([in3.m4], -[[include(`.') -]]) - -AT_CHECK_M4([in1.m4/], [1], [], [stderr]) -dnl mingw fails with EINVAL rather than the expected ENOTDIR -AT_CHECK([$SED 's/Invalid argument/Not a directory/' stderr], [0], -[[m4: cannot open file 'in1.m4/': Not a directory -]]) - -AT_CHECK_M4([in1.m4], [1], [[ -]], [stderr]) -dnl mingw fails with EINVAL rather than the expected ENOTDIR -AT_CHECK([$SED 's/Invalid argument/Not a directory/' stderr], [0], -[[m4:in1.m4:1: include: cannot open file 'in2.m4/': Not a directory -]]) - -AT_CHECK_M4([in2.m4], [0], [[ - -]]) - -AT_CHECK_M4([in3.m4], [1], [[ -]], [stderr]) -dnl mingw fails with EACCES rather than the expected EISDIR -AT_CHECK([$SED 's/Permission denied/Is a directory/' stderr], [0], -[[m4:in3.m4:1: include: cannot open file '.': Is a directory -]]) - -AT_CLEANUP - - -## ------- ## -## foreach ## -## ------- ## - -AT_SETUP([foreach]) - -AT_DATA([[foreach.m4]], -[[divert(-1) -# foreach(x, (item_1, item_2, ..., item_n), stmt) -define(`foreach', `pushdef(`$1', `')_foreach($@)popdef(`$1')') -define(`_arg1', ``$1'') -define(`_foreach', - `ifelse($2, `()', , - `define(`$1', `_arg1$2')$3`'_foreach(`$1', `(shift$2)', `$3')')') - -# traceon(`define', `foreach', `_foreach', `ifelse') - -define(a, 1) -define(b, 2) -define(c, 3) -divert -foreach(`x', `(foo, bar, foobar)', `Word was: x -') - -# Quote torture from Akim Demaille -foreach(`x', `(`a', `(b', `c)')', `Word was: x -') - -# Something more complex, from Pierre Gaumond . -define(`case', ` $1) - $2=" -$1";; -')dnl -define(`_cat', `$1$2')dnl -`case' "$1" in -foreach(`x', ((a, vara), (b, varb), (c, varc)), `_cat(`case', x)')dnl -esac -]]) - -AT_CHECK_M4([foreach.m4], 0, -[[ -Word was: foo -Word was: bar -Word was: foobar - - -# Quote torture from Akim Demaille -Word was: a -Word was: (b -Word was: c) - - -# Something more complex, from Pierre Gaumond . -case "$1" in - 1) - vara=" -1";; - 2) - varb=" -2";; - 3) - varc=" -3";; -esac -]]) - -AT_CLEANUP - - - -## ------- ## -## forloop ## -## ------- ## - -AT_SETUP([forloop]) - -AT_DATA([[forloop.m4]], -[[divert(-1) -# forloop(i, from, to, stmt) - -define(`forloop', `pushdef(`$1', `$2')_forloop(`$1', `$2', `$3', `$4')popdef(`$1')') -define(`_forloop', - `$4`'ifelse($1, `$3', , - `define(`$1', incr($1))_forloop(`$1', `$2', `$3', `$4')')') -divert -forloop(`x', 1, 10, `2**x = eval(2**x) -') -]]) - -AT_CHECK_M4([forloop.m4], 0, -[[ -2**1 = 2 -2**2 = 4 -2**3 = 8 -2**4 = 16 -2**5 = 32 -2**6 = 64 -2**7 = 128 -2**8 = 256 -2**9 = 512 -2**10 = 1024 - -]]) - -AT_CLEANUP - - - -## ----- ## -## fstab ## -## ----- ## - -AT_SETUP([fstab]) - -AT_DATA([[fstab.m4]], -[[define(`concat', `translit(``$*'', ` ')') -define(`fsent', `format(`%-25s %-16s nfs %-16s 0 0', `$1:$2', `$3', concat$4)') - -fsent(freja, /home/gevn, /home/gevn, (rw, soft, bg, grpid)) -fsent(freja, /home/freja, /home/freja, (rw, soft, grpid)) -fsent(rimfaxe, /home/rimfaxe, /home/rimfaxe, (rw, soft, bg)) - -]]) - -AT_CHECK_M4([fstab.m4], 0, -[[ - - -freja:/home/gevn /home/gevn nfs rw,soft,bg,grpid 0 0 -freja:/home/freja /home/freja nfs rw,soft,grpid 0 0 -rimfaxe:/home/rimfaxe /home/rimfaxe nfs rw,soft,bg 0 0 - -]]) - -AT_CLEANUP - - - -## ----- ## -## hanoi ## -## ----- ## - -AT_SETUP([hanoi]) - -AT_DATA([[hanoi.m4]], -[[divert(-1) - -# move(from, to) -define(`move', `Move one disk from `$1' to `$2'. -') - -# _hanoi (cnt, from, to, aux) -define(`_hanoi', `ifelse(eval(`$1'<=1), 1, `move($2, $3)', -`_hanoi(decr($1), $2, $4, $3)move($2, $3)_hanoi(decr($1), $4, $3, $2)')') - -# hanoi (cnt) -define(`hanoi', `_hanoi(`$1', source, destination, auxilliary)') - -# traceon(`move', `_hanoi', `decr') -divert`'dnl - -hanoi(3) -]]) - -AT_CHECK_M4([hanoi.m4], 0, -[[ -Move one disk from source to destination. -Move one disk from source to auxilliary. -Move one disk from destination to auxilliary. -Move one disk from source to destination. -Move one disk from auxilliary to source. -Move one disk from auxilliary to destination. -Move one disk from source to destination. - -]]) - -AT_CLEANUP - - -## ------ ## -## ifndef ## -## ------ ## - -AT_SETUP([ifndef]) - -dnl This catches a bug added 2008-03-13, fixed 2008-04-10. -AT_DATA([in.m4], -[[define(`ifndef', `ifdef(`$1', `$3', `$2')')dnl -define(`a_really_long_name', `1')dnl -ifdef(`divnum', `yes', `no') -ifndef(`divnum', `yes', `no') -ifdef(`ifndef', `yes', `no') -ifndef(`ifndef', `yes', `no') -ifdef(`a_really_long_name', `yes', `no') -ifndef(`a_really_long_name', `yes', `no') -ifdef(`no_such', `yes', `no') -ifndef(`no_such', `yes', `no') -]]) - -AT_CHECK_M4([in.m4], [0], -[[yes -no -yes -no -yes -no -no -yes -]]) - -AT_CLEANUP - - -## ------- ## -## iso8859 ## -## ------- ## - -AT_SETUP([iso8859]) - -# Eh eh eh... -# We can't embed iso8859.m4 in here since it includes a NUL character, -# and we can't yet rely on autom4te being NUL-clean (even though this -# test shows that M4 is trying to be NUL-clean). - -AT_DATA([[expout]], -[[# Testing quotes -DEFINE # eol -CHANGEQUOTE(«,») # eol -0 TEST # TEST -1 test # test -2 «test» # «test» -3 ««test»» # ««test»» -CHANGEQUOTE(«««,»»») # eol -0 TEST # TEST -1 «TEST» # «TEST» -2 ««TEST»» # ««TEST»» -3 test # test -# Test use of all iso8859 characters except ^Z (win32 EOF) and NUL ` ' -Length of string is: 254 -Comparing strings: MATCH -# NUL passes through now! -42 -]]) - -AT_CHECK_M4(["$abs_srcdir/iso8859.m4"], 0, expout) - -AT_CLEANUP - - -## ------------- ## -## nul character ## -## ------------- ## - -AT_SETUP([nul character]) - -# Operating on a binary file is a GNU sed extension. -AT_CHECK([test `printf 'a\0b\n' | $SED s/a.b/abc/ | wc -c` = 4 dnl -|| { echo "skipping: $SED can't handle NUL"; exit 77; }]) - -# We don't embed null.* in here, since it is harder to guarantee the -# behavior of NUL through autom4te. -$SED "s|null.m4|$abs_srcdir/null.m4|" < "$abs_srcdir/null.out" > expout -$SED "s|null.m4|$abs_srcdir/null.m4|" < "$abs_srcdir/null.err" > experr - -dnl all but m4exit -AT_CHECK_M4([-Dm4exit -I "$abs_srcdir" null.m4], [1], [expout], [experr]) - -dnl just m4exit -AT_CHECK_M4(["$abs_srcdir/null.m4"], [1], -[[# This file tests m4 behavior on NUL bytes. -]], [stderr]) -AT_CHECK([sed "s|$abs_srcdir/||" stderr], [0], -[[m4:null.m4:5: warning: m4exit: non-numeric argument '2\0002' -]]) - -AT_CLEANUP - - -## --------- ## -## recursion ## -## --------- ## - -AT_SETUP([recursion]) - -dnl This input exploits contents of loop.m4 to print out the final value -dnl of the recursion. -AT_DATA([in.m4], -[[define(`foo', `divert`'len(popdef(`_foreachq')_foreachq($@))')dnl -define(`debug', `pushdef(`_foreachq', defn(`foo'))')dnl -include(`loop.m4')dnl -]]) - -dnl boxed recursion -AT_CHECK_M4([-I "$top_srcdir/doc/examples" -Dlimit=10 -Dverbose loop.m4], [0], -[[ 1 2 3 4 5 6 7 8 9 10 -]]) -AT_CHECK_M4([-I "$top_srcdir/doc/examples" -Dlimit=2500 loop.m4], [0]) -AT_CHECK_M4([-I "$top_srcdir/doc/examples" -Dlimit=10000 in.m4], [0], [[48894 -]]) - -dnl unboxed recursion -AT_CHECK_M4([-I "$top_srcdir/doc/examples" -Dlimit=10 -Dverbose -Dalt loop.m4], [0], -[[ 1 2 3 4 5 6 7 8 9 10 -]]) -AT_CHECK_M4([-I "$top_srcdir/doc/examples" -Dlimit=2500 -Dalt loop.m4], [0]) -AT_CHECK_M4([-I "$top_srcdir/doc/examples" -Dlimit=10000 -Dalt in.m4], [0], -[[48894 -]]) - -dnl foreach via forloop recursion -AT_CHECK_M4([-I "$top_srcdir/doc/examples" -Dlimit=10 -Dverbose -Dalt=4 loop.m4], -[0], [[ 1 2 3 4 5 6 7 8 9 10 -]]) -AT_CHECK_M4([-I "$top_srcdir/doc/examples" -Dlimit=2500 -Dalt=4 loop.m4], [0]) -AT_CHECK_M4([-I "$top_srcdir/doc/examples" -Dlimit=10000 -Dalt=4 in.m4], [0], -[[48894 -]]) - -dnl foreach via definition stack -AT_DATA([in.m4], [[include(`forloop3.m4')include(`stack_sep.m4')dnl -forloop(`i', `1', `10000', `pushdef(`s', i)')dnl -define(`colon', `:')define(`dash', `-')dnl -len(stack_foreach_sep(`s', `dash', `', `colon')) -]]) -AT_CHECK_M4([-I "$top_srcdir/doc/examples" in.m4], [0], [[58893 -]]) - -AT_CLEANUP - - -## ------- ## -## reverse ## -## ------- ## - -AT_SETUP([reverse]) - -AT_DATA([[reverse.m4]], -[[define(`reverse', `ifelse(eval($# > 1), 1, `reverse(shift($@)), `$1'', ``$1'')') -``'' => reverse. -``hej'' => reverse(hej). -``hej, med, dig'' => reverse(hej, med, dig). -]]) - -AT_CHECK_M4([reverse.m4], 0, -[[ -`' => . -`hej' => hej. -`hej, med, dig' => dig, med, hej. -]]) - -AT_CLEANUP - - -## ------------- ## -## stderr closed ## -## ------------- ## - -AT_SETUP([stderr closed]) - -dnl no error when stderr is not used -AT_CHECK_M4([2>&-], [0]) - -dnl no error when stderr is not used -AT_DATA([in.m4], [[hello world -]]) -AT_CHECK_M4([2>&-], [0], [[hello world -]], [], [in.m4]) - -dnl must exit nonzero when error issued -AT_CHECK_M4([--unknown 2>&-], [1]) - -dnl must exit nonzero if stderr used -AT_DATA([in.m4], [[errprint(`hello world -')dnl -]]) -AT_CHECK_M4([2>&-], [1], [], [], [in.m4]) - -dnl must exit nonzero if stderr used -AT_DATA([in.m4], [[hello -dnl(`world') -]]) -AT_CHECK_M4([2>&-], [1], [[hello -]], [], [in.m4]) - -dnl must exit nonzero on error, in spite of m4exit requesting 0 -AT_DATA([in.m4], [[errprint(`hello world -')m4exit(`0') -]]) -AT_CHECK_M4([2>&-], [1], [], [], [in.m4]) - -dnl preserve m4exit's failure value -AT_DATA([in.m4], [[errprint(`hello world -')m4exit(`2') -]]) -AT_CHECK_M4([2>&-], [2], [], [], [in.m4]) - -dnl trace file must not collide with closed stderr -AT_DATA([in.m4], [[errprint(`hello world -')dnl -]]) -AT_CHECK_M4([--debugfile=trace -terrprint 2>&-], [1], [], [], [in.m4]) -AT_CHECK([cat trace], [0], [[m4trace: -1- errprint(`hello world -') -> `' -]]) - -dnl spilled diversion file must not collide with closed stderr -AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(1)f -and`'dnl(not) -divert -hello`'dnl(world) -undivert -goodbye -]]) -AT_CHECK_M4([2>&-], [1], [stdout-nolog], [], [in.m4]) -AT_CHECK([$SED -ne '/./p' stdout], [0], -[[hello -and -goodbye -]]) - -dnl command line input file must not collide with closed stderr -AT_DATA([in.m4], [[syscmd(`echo <&2')ifelse(sysval, -`0', `skipping: sh cannot detect closed fds -m4exit(`77')') -]]) -AT_CHECK_M4([2>&-], [0], [ignore], [ignore], [in.m4]) -AT_DATA([in.m4], [[syscmd(`cat <&2')sysval -dnl this line should not be read by cat -]]) -AT_CHECK_M4([2>&-], [0], [[1 -]], [], [in.m4]) -AT_CHECK_M4([in.m4 2>&-], [0], [[1 -]]) - -AT_CLEANUP - - -## ------------ ## -## stdin closed ## -## ------------ ## - -AT_SETUP([stdin closed]) - -dnl no error when stdin is not used due to early exit -AT_CHECK_M4([--version], [0], [ignore], [], [-]) - -dnl no error when stdin is not used due to supplied file -AT_DATA([in.m4], [[hello world -]]) -AT_CHECK_M4([in.m4], [0], [[hello world -]], [], [-]) - -dnl Some systems reopen closed stdin to /dev/null, particularly when using -dnl the shell script tests/m4 instead of a binary src/m4. -AT_CHECK([cat <&- && { echo "skipping: can't detect closed stdin"; exit 77; }], -[1], [], [stderr]) -mv stderr experr -AT_DATA([in.m4], [[syscmd(`cat')ifelse(sysval, -`0', `skipping: unable to start with closed stdin -m4exit(`77')') -]]) -AT_CHECK_M4([in.m4], [0], [ignore], [ignore], [-]) - -dnl error when stdin must be read -AT_CHECK_M4([], [1], [], -[[m4:stdin:1: error reading 'stdin' -m4: error closing file: Bad file descriptor -]], [-]) - -dnl error when stdin must be read -AT_CHECK_M4([-], [1], [], -[[m4:stdin:1: error reading 'stdin' -m4: error closing file: Bad file descriptor -]], [-]) - -dnl error once per command-line attempt to read stdin -AT_DATA([in.m4], [[hello world -]]) -AT_CHECK_M4([- in.m4 -], [1], [[hello world -]], [[m4:stdin:1: error reading 'stdin' -m4:stdin:1: error reading 'stdin' -m4: error closing file: Bad file descriptor -]], [-]) - -dnl command line and trace file must not collide with stdin -AT_DATA([in.m4], [[syscmd(`cat')dnl -]]) -AT_CHECK_M4([--debugfile=trace -tdnl in.m4], [0], [], [experr], [-]) -AT_CHECK([cat trace], [0], [[m4trace: -1- dnl -> `' -]]) - -dnl diversions must not collide with stdin -AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(`1')f -syscmd(`cat')dnl -divert(`-1')undivert -]]) -AT_CHECK_M4([in.m4], [0], [], [experr], [-]) - -dnl diversions must not collide with stdin -AT_DATA([in.m4], [M4_ONE_MEG_DEFN[hello divert(`1')f -]]) -AT_DATA([in2.m4], [[divert(`-1')undivert -divert`'world -]]) -AT_CHECK_M4([in.m4 - in2.m4], [1], [[hello world -]], [[m4:stdin:1: error reading 'stdin' -m4: error closing file: Bad file descriptor -]], [-]) - -AT_CLEANUP - -## -------------- ## -## stdin seekable ## -## -------------- ## - -AT_SETUP([stdin seekable]) - -dnl POSIX requires that if stdin is seekable, m4 must seek to the location -dnl of unprocessed data for the benefit of other copies of the fd. - -dnl Check internal follow-on process. -AT_DATA([in.m4], [[syscmd(`cat')m4exit(15) -]]) -AT_CHECK_M4([], [0], [[m4exit(15) -]], [], [in.m4]) - -dnl Check external follow-on process, after m4exit. -AT_DATA([in.m4], [[m4exit( -0)trailing data -]]) -AT_CHECK([($M4; cat) < in.m4], [0], [[trailing data -]]) - -dnl Check external follow-on process, after fatal error. -dnl We can't use AT_CHECK_M4, so we must post-process stderr ourselves. -AT_DATA([in.m4], [[dnl( -0)trailing data -]]) -AT_CHECK([($M4 -EE; cat) < in.m4], [0], [[trailing data -]], [stderr]) -AT_CHECK([[$SED 's/^[^:]*[lt-]*m4[.ex]*:/m4:/' stderr]], [0], -[[m4:stdin:1: warning: dnl: extra arguments ignored: 1 > 0 -]]) - -dnl Not all sed and libc combinations get the remaining tests right (for -dnl example, sed 4.1.4 on glibc, or cygwin 1.5.22 and earlier). -AT_CHECK([($SED -ne 1q; cat) < in.m4], [0], [stdout]) -AT_CHECK([test "x`cat stdout`" = "x0)trailing data" || \ - { echo "skipping: $SED is too greedy on seekable stdin"; exit 77; }]) - -dnl Ensure that esyscmd resumes parsing where the child process left off. -AT_DATA([in.m4], [[define(`foo', `FOO')m4 foo -esyscmd(`$SED -e "s/foo/bar/;q"')sed foo -m4 foo -]]) -AT_CHECK_M4([], [0], [[m4 FOO -sed bar -m4 FOO -]], [], [in.m4]) - -dnl Ensure that syscmd resumes parsing where the child process left off. -AT_DATA([in.m4], [[define(`foo', `FOO')m4 foo -syscmd(`$SED -e "s/foo/bar/;q"')sed foo -m4 foo -]]) -AT_CHECK_M4([], [0], [[m4 FOO -sed bar -m4 FOO -]], [], [in.m4]) - -AT_CLEANUP - -## ----------------------- ## -## stdin and stdout closed ## -## ----------------------- ## - -AT_SETUP([stdin and stdout closed]) - -dnl no error when only stderr is used -AT_DATA([in.m4], [[esyscmd(echo hi >&2 && echo err"print(bye -)d"nl)dnl -]]) -AT_CHECK_M4([in.m4 >&-], [0], [], [[hi -bye -]], [-]) - -AT_CLEANUP - -## ------------- ## -## stdout closed ## -## ------------- ## - -AT_SETUP([stdout closed]) - -dnl error when stdout must be used -AT_CHECK_M4([--version >&-], [1], [], -[[m4: write error: Bad file descriptor -]]) - -dnl no error when stdout is not used -AT_CHECK_M4([>&-], [0]) - -dnl no error when stdout is not used -AT_DATA([in.m4], [[errprint(`hello world -')dnl -]]) -AT_CHECK_M4([>&-], [0], [], [[hello world -]], [in.m4]) - -dnl error when stdout must be used -AT_CHECK_M4([-P >&-], [1], [], -[[m4: write error: Bad file descriptor -]], [in.m4]) - -dnl error must occur in spite of m4exit requesting 0 -AT_DATA([in.m4], [[hello world -m4exit(`0') -]]) -AT_CHECK_M4([>&-], [1], [], -[[m4:stdin:2: write error: Bad file descriptor -]], [in.m4]) - -dnl preserve m4exit's failure value -AT_DATA([in.m4], [[hello world -m4exit(`2') -]]) -AT_CHECK_M4([>&-], [2], [], -[[m4:stdin:2: write error: Bad file descriptor -]], [in.m4]) - -dnl trace file must not collide with closed stdout -AT_DATA([in.m4], [[hello world -dnl -]]) -AT_CHECK_M4([--debugfile=trace -tdnl >&-], [1], [], -[[m4: write error: Bad file descriptor -]], [in.m4]) -AT_CHECK([cat trace], [0], [[m4trace: -1- dnl -> `' -]]) - -dnl esyscmd always has valid stdout -AT_DATA([in.m4], [[errprint(esyscmd(`echo hello'))dnl -]]) -AT_CHECK_M4([>&-], [0], [], [[hello -]], [in.m4]) - -dnl syscmd inherits closed stdout -AT_DATA([hi], [[hi -]]) -AT_CHECK([cat hi >&- && { echo "skipping: can't detect closed stdout"; exit 77; }], -[1], [], [stderr]) -AT_CHECK([$SED 's/Bad file number/Bad file descriptor/' < stderr > experr]) -AT_DATA([in.m4], [[syscmd(`cat hi')dnl -]]) -AT_CHECK_M4([>&-], [0], [], [experr], [in.m4]) - -dnl spilled diversion file must not collide with closed stdout -AT_DATA([in.m4], [M4_ONE_MEG_DEFN[divert(1)f -syscmd(`cat hi') -divert(`-1')undivert -]]) -AT_CHECK_M4([>&-], [0], [], [experr], [in.m4]) - -dnl command line input file must not collide with closed stdout -AT_DATA([in.m4], [[syscmd(`echo <&2')ifelse(sysval, -`0', `skipping: sh cannot detect closed fds -m4exit(`77')') -]]) -AT_CHECK_M4([2>&-], [0], [ignore], [ignore], [in.m4]) -AT_DATA([in.m4], [[syscmd(`cat <&1 >&2')dnl -dnl this line should not be read by cat -]]) -AT_CHECK_M4([in.m4 >&-], [0], [], [stderr]) -AT_CHECK([[$SED -e 's/.*[Bb]\(ad file descriptor\)$/B\1/' stderr]], [0], -[[Bad file descriptor -]]) - -AT_CLEANUP - - -## ----------- ## -## stdout full ## -## ----------- ## - -AT_SETUP([stdout full]) -AT_CHECK([test -w /dev/full && test -c /dev/full || { - echo "skipping: no /dev/full support"; - exit 77 -}]) - -dnl Be careful when modifying these tests. Writes that exceed stdio buffering -dnl limits trigger different but legal behavior where errno is lost. Tests -dnl that currently require "No space left on device" may fail if the amount of -dnl output changes. The --help test shows how to handle this. - -dnl detect write failures on --help -AT_CHECK_M4([--help >/dev/full], [1], [], [stderr]) -AT_CHECK([grep '^m4: write error' stderr], [0], [ignore]) - -dnl detect write failures on --version -AT_CHECK_M4([--version >/dev/full], [1], [], -[[m4: write error: No space left on device -]]) - -dnl detect ordinary write failures -AT_DATA([in.m4], [[hello world -]]) -AT_CHECK_M4([in.m4 >/dev/full], [1], [], -[[m4: write error: No space left on device -]]) - -dnl detect stderr write failures -AT_DATA([in.m4], [[dnl(hello world) -]]) -AT_CHECK_M4([in.m4 2>/dev/full], [1]) - -dnl detect trace write failures -AT_DATA([in.m4], [[dnl -]]) -AT_CHECK_M4([-tdnl in.m4 2>/dev/full], [1]) - -dnl detect trace write failures -AT_DATA([in.m4], [[dnl -]]) -AT_CHECK_M4([--debugfile=/dev/full -tdnl in.m4], [1], [], -[[m4: error writing to debug stream: No space left on device -]]) - -dnl too hard to test for spilled diversion failures, without requiring the -dnl user to have a nearly full partition that we can assign to $TMPDIR. - -dnl write failures must override m4exit requesting 0 -AT_DATA([in.m4], [[hello world m4exit(`0') -]]) -AT_CHECK_M4([in.m4 >/dev/full], [1], [], -[[m4:in.m4:1: write error: No space left on device -]]) - -dnl preserve m4exit's failure value -AT_DATA([in.m4], [[hello world m4exit(`2') -]]) -AT_CHECK_M4([in.m4 >/dev/full], [2], [], -[[m4:in.m4:1: write error: No space left on device -]]) - -AT_CLEANUP - - -## --------- ## -## sysv-args ## -## --------- ## - -AT_SETUP([sysv-args]) - -AT_DATA([[sysv-args.m4]], -[[divert(-1) -define(`nargs', `$#') -define(`concat', `ifelse(1, $#, `$1', `$1` 'concat(shift($@))')') -traceon(`concat', `nargs') -divert - -nargs -nargs() -nargs(1,2,3,4,5,6) - -concat() -concat(`hej', `med', `dig') -concat(`hej', `med', `dig', `en gang igen') -concat(an, awful, lot, of, argument, at, least, more, that, ten, silly, arguments) -]]) - -AT_DATA([[expout]], -[[ - -0 -1 -6 - - -hej med dig -hej med dig en gang igen -an awful lot of argument at least more that ten silly arguments -]]) - -AT_DATA([[experr]], -[[m4trace: -1- nargs -> `0' -m4trace: -1- nargs(`') -> `1' -m4trace: -1- nargs(`1', `2', `3', `4', `5', `6') -> `6' -m4trace: -1- concat(`') -> `ifelse(1, 1, `', `` 'concat(shift(`'))')' -m4trace: -1- concat(`hej', `med', `dig') -> `ifelse(1, 3, `hej', `hej` 'concat(shift(`hej',`med',`dig'))')' -m4trace: -1- concat(`med', `dig') -> `ifelse(1, 2, `med', `med` 'concat(shift(`med',`dig'))')' -m4trace: -1- concat(`dig') -> `ifelse(1, 1, `dig', `dig` 'concat(shift(`dig'))')' -m4trace: -1- concat(`hej', `med', `dig', `en gang igen') -> `ifelse(1, 4, `hej', `hej` 'concat(shift(`hej',`med',`dig',`en gang igen'))')' -m4trace: -1- concat(`med', `dig', `en gang igen') -> `ifelse(1, 3, `med', `med` 'concat(shift(`med',`dig',`en gang igen'))')' -m4trace: -1- concat(`dig', `en gang igen') -> `ifelse(1, 2, `dig', `dig` 'concat(shift(`dig',`en gang igen'))')' -m4trace: -1- concat(`en gang igen') -> `ifelse(1, 1, `en gang igen', `en gang igen` 'concat(shift(`en gang igen'))')' -m4trace: -1- concat(`an', `awful', `lot', `of', `argument', `at', `least', `more', `that', `ten', `silly', `arguments') -> `ifelse(1, 12, `an', `an` 'concat(shift(`an',`awful',`lot',`of',`argument',`at',`least',`more',`that',`ten',`silly',`arguments'))')' -m4trace: -1- concat(`awful', `lot', `of', `argument', `at', `least', `more', `that', `ten', `silly', `arguments') -> `ifelse(1, 11, `awful', `awful` 'concat(shift(`awful',`lot',`of',`argument',`at',`least',`more',`that',`ten',`silly',`arguments'))')' -m4trace: -1- concat(`lot', `of', `argument', `at', `least', `more', `that', `ten', `silly', `arguments') -> `ifelse(1, 10, `lot', `lot` 'concat(shift(`lot',`of',`argument',`at',`least',`more',`that',`ten',`silly',`arguments'))')' -m4trace: -1- concat(`of', `argument', `at', `least', `more', `that', `ten', `silly', `arguments') -> `ifelse(1, 9, `of', `of` 'concat(shift(`of',`argument',`at',`least',`more',`that',`ten',`silly',`arguments'))')' -m4trace: -1- concat(`argument', `at', `least', `more', `that', `ten', `silly', `arguments') -> `ifelse(1, 8, `argument', `argument` 'concat(shift(`argument',`at',`least',`more',`that',`ten',`silly',`arguments'))')' -m4trace: -1- concat(`at', `least', `more', `that', `ten', `silly', `arguments') -> `ifelse(1, 7, `at', `at` 'concat(shift(`at',`least',`more',`that',`ten',`silly',`arguments'))')' -m4trace: -1- concat(`least', `more', `that', `ten', `silly', `arguments') -> `ifelse(1, 6, `least', `least` 'concat(shift(`least',`more',`that',`ten',`silly',`arguments'))')' -m4trace: -1- concat(`more', `that', `ten', `silly', `arguments') -> `ifelse(1, 5, `more', `more` 'concat(shift(`more',`that',`ten',`silly',`arguments'))')' -m4trace: -1- concat(`that', `ten', `silly', `arguments') -> `ifelse(1, 4, `that', `that` 'concat(shift(`that',`ten',`silly',`arguments'))')' -m4trace: -1- concat(`ten', `silly', `arguments') -> `ifelse(1, 3, `ten', `ten` 'concat(shift(`ten',`silly',`arguments'))')' -m4trace: -1- concat(`silly', `arguments') -> `ifelse(1, 2, `silly', `silly` 'concat(shift(`silly',`arguments'))')' -m4trace: -1- concat(`arguments') -> `ifelse(1, 1, `arguments', `arguments` 'concat(shift(`arguments'))')' -]]) - -AT_CHECK_M4([sysv-args.m4], 0, [expout], [experr]) - -AT_CLEANUP diff --git a/tests/shadow.c b/tests/shadow.c deleted file mode 100644 index ae8cac7d..00000000 --- a/tests/shadow.c +++ /dev/null @@ -1,91 +0,0 @@ -/* GNU m4 -- A simple macro processor - Copyright (C) 1999-2000, 2006-2008, 2010, 2013-2014, 2017 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 . -*/ - -#include - -/* Build using only the exported interfaces, unless NDEBUG is set, in - which case use private symbols to speed things up as much as possible. */ -#ifndef NDEBUG -# include -#else -# include "m4private.h" -#endif - -/* function macros blind side minargs maxargs */ -#define builtin_functions \ - BUILTIN (shadow, false, false, false, 0, -1 ) \ - BUILTIN (test, false, false, false, 0, -1 ) \ - - -#define BUILTIN(handler, macros, blind, side, min, max) M4BUILTIN (handler) - builtin_functions -#undef BUILTIN - -static const m4_builtin m4_builtin_table[] = -{ -#define BUILTIN(handler, macros, blind, side, min, max) \ - M4BUILTIN_ENTRY (handler, #handler, macros, blind, side, min, max) - - builtin_functions -#undef BUILTIN - - { NULL, NULL, 0, 0, 0 }, -}; - -static const m4_macro m4_macro_table[] = -{ - /* name text min max */ - { "__test__", "`shadow'", 0, 0 }, - { NULL, NULL, 0, 0 }, -}; - - - -void -include_shadow (m4 *context, m4_module *module, m4_obstack *obs) -{ - const char *s = "Shadow module loaded."; - - if (obs) - obstack_grow (obs, s, strlen (s)); - - m4_install_builtins (context, module, m4_builtin_table); - m4_install_macros (context, module, m4_macro_table); -} - - - -/** - * shadow() - **/ -M4BUILTIN_HANDLER (shadow) -{ - const char *s = "Shadow::`shadow' called."; - obstack_grow (obs, s, strlen (s)); -} - -/** - * test() - **/ -M4BUILTIN_HANDLER (test) -{ - const char *s = "Shadow::`test' called."; - obstack_grow (obs, s, strlen (s)); -} diff --git a/tests/stackovf.test b/tests/stackovf.test deleted file mode 100755 index d57fc0f0..00000000 --- a/tests/stackovf.test +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/sh -# This file is part of the GNU m4 testsuite -# Copyright (C) 2000, 2003, 2007, 2010, 2013-2014, 2017 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 . - -exit 77 - -# 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=../../src/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 -#strace -o /tmp/aaa $M4 -L999999999 > $tmpfile 2>&1 -$M4 -L999999999 > $tmpfile 2>&1 -) -result=$? -{ echo "Output from $M4:"; cat $tmpfile; } - -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*|*emory*xhausted) - 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/tests/testsuite.at b/tests/testsuite.at deleted file mode 100644 index 19fc9ee7..00000000 --- a/tests/testsuite.at +++ /dev/null @@ -1,180 +0,0 @@ -# Process with autom4te to create an -*- Autotest -*- test suite. - -# Test suite for GNU M4. -# Copyright (C) 2001, 2006-2010, 2013-2014, 2017 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 . - -# We need a recent Autotest. -m4_version_prereq([2.63b-41]) - -# Default to testing "m4 -b", but allow overrides. -dnl This uses knowledge of undocumented autotest internals; hopefully -dnl it isn't too much of a problem. FIXME: Help autoconf document -dnl proper usage of HELP_OTHER, at_write_fail, and at_tested (or better -dnl yet, add AT_FOO macros that wrap these internal details). -m4_divert_text([HELP_OTHER], -[cat <<\_ATEOF || at_write_fail=1 - -The environment variable `M4' controls which binary is tested, default `m4 -b'. -_ATEOF]) -m4_divert_text([PREPARE_TESTS], -[[if test "${M4+set}" = set; then - case $M4 in - *[\\/]* ) at_tested= ;; - * ) at_tested=`set x $M4; echo $2` ;; - esac -else - M4='m4 -b' -fi]]) - -# AT_CHECK_M4(ARGS, [EXIT-STATUS = 0], [STDOUT = `'], [STDERR = `'], -# [STDIN = `/dev/null'], [INHIBIT-D]) -# ------------------------------------------------------------------ -# Run m4 with ARGS, and stdin redirected from STDIN, or with stdin closed -# if STDIN is `-'. ARGS may redirect stdout and/or stderr, but should -# not redirect stdin. Expect EXIT-STATUS, with output matching STDOUT and -# STDERR as in AT_CHECK. If STDERR is specified, normalize the observed -# error output. Unless INHIBIT-D is specified, add -d prior to ARGS. -# -# When testing an uninstalled wrapper, tests/m4 is on the path, but invokes -# src/m4, which may itself be a libtool wrapper. Also, some platforms -# choose to display argv[0] differently: -# path/to/lt-m4:file:line: message -# or m4.exe:file:line: message -# to m4:file:line -# -# When testing closed file descriptors, the message is platform-dependent: -# m4: error closing file: Bad file number -# to m4: error closing file: Bad file descriptor -# -# When tracing modules, the module name is platform-dependent: -# m4debug: module gnu: opening file `gnu.so' -# or m4debug: module gnu: opening file `gnu.a' -# to m4debug: module gnu: opening file -# -# When testing modules, a failed module name is platform-dependent: -# m4:input.m4:7: cannot open module `no_such': no_such.so: cannot open shared object file: No such file or directory -# or m4:input.m4:7: cannot open module `no_such': can't open the module -# to m4:input.m4:7: cannot open module `no_such' -# -# When encountering command line option errors, the error message is -# platform-dependent, but contains " option ": -# m4: unrecognized option `--diversions=1' # glibc 2.6 -# or m4: unrecognized option '--diversions=1' # glibc 2.11 -# or m4: unknown option -- --diversions # BSD -# or m4: option '--debu' is ambiguous # glibc 2.11 -# or m4: ambiguous option -- --debu # BSD -# to m4: bad option -m4_define([AT_CHECK_M4], -[AT_CHECK([$M4 m4_ifval([$6], [], [-d ])$1 ]m4_if([$5], [-], [<&-], - [< m4_default([$5], [/dev/null])]), - [$2], [$3], m4_case([$4], [], [], [ignore], [ignore], [stderr])) -m4_case([$4], [], [], [ignore], [], -[AT_CHECK([[$SED 's/^[^:]*[lt-]*m4[.ex]*:/m4:/ - /^m4debug: module/s/opening file.*/opening file/ - s/\(cannot open module [^:]*\):.*/\1/ - s/Bad file number/Bad file descriptor/ - s/^m4:.* option .*/m4: bad option/ - ' stderr >&2]], [0], [], [$4])]) -]) - -# M4_ONE_MEG_DEFN -# --------------- -# emit a code snippet for use in AT_DATA that will define a macro `f' to -# consist of 1M bytes of newlines. With that in place, it is then easy -# to use divert and invoke `f' in the test file to force diversions to -# spill into a temporary file. -m4_define([M4_ONE_MEG_DEFN], -[pushdef(`diversion', divnum)divert(-1) -define(`f', ` -') -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -define(`f', defn(`f')defn(`f')) -divert(diversion)popdef(`diversion')]) - -# AT_TEST_M4(TITLE, INPUT, [STDOUT = `'], [STDERR = `']) -# ------------------------------------------------------ -# Run m4 on INPUT, expecting a success. -m4_define([AT_TEST_M4], -[AT_SETUP([$1]) -AT_DATA([[input.m4]], [$2]) -AT_CHECK_M4([[input.m4]], 0, [$3], [$4]) -AT_CLEANUP -]) - -# We use `dnl' in zillions of places... -m4_pattern_allow([^dnl$]) - -# We exercise m4. -AT_TESTED([m4]) - -# AT_CHECK_GMP -# ----------------------- -# Add keyword `gmp' to the test, and skip the test if the use of GMP -# was disabled at configure time. -m4_define([AT_CHECK_GMP], -[AT_KEYWORDS([gmp]) -AT_CHECK([if test "x$USE_GMP" = xno ; then - echo libgmp support not detected, skipping this test. - exit 77 -fi])]) - -## ----------- ## -## The suite. ## -## ----------- ## - -AT_INIT - -# Macro definitions, uses, tracing etc. -m4_include([macros.at]) - -# Torturing builtins. -m4_include([builtins.at]) - -# Options. -m4_include([options.at]) - -# Frozen files. -m4_include([freeze.at]) - -# Hand crafted tests. -m4_include([others.at]) - -# Torturing the modules support. -m4_include([modules.at]) - -# From the documention. -m4_include([generated.at]) -- cgit v1.2.1